]> git.openstreetmap.org Git - rails.git/commitdiff
Merge remote-tracking branch 'upstream/pull/2042'
authorTom Hughes <tom@compton.nu>
Sun, 4 Nov 2018 14:49:27 +0000 (14:49 +0000)
committerTom Hughes <tom@compton.nu>
Sun, 4 Nov 2018 14:49:27 +0000 (14:49 +0000)
62 files changed:
.mailmap
.rubocop_todo.yml
.travis.yml
Gemfile
Gemfile.lock
app/abilities/ability.rb [new file with mode: 0644]
app/abilities/capability.rb [new file with mode: 0644]
app/assets/stylesheets/common.scss
app/controllers/application_controller.rb
app/controllers/changeset_controller.rb
app/controllers/diary_entry_controller.rb
app/controllers/issue_comments_controller.rb
app/controllers/issues_controller.rb
app/controllers/messages_controller.rb
app/controllers/notes_controller.rb
app/controllers/reports_controller.rb
app/controllers/site_controller.rb
app/controllers/user_preferences_controller.rb
app/controllers/users_controller.rb
app/mailers/notifier.rb [moved from app/models/notifier.rb with 100% similarity]
app/models/concerns/geo_record.rb [moved from lib/geo_record.rb with 89% similarity]
app/models/concerns/not_redactable.rb [moved from lib/not_redactable.rb with 78% similarity]
app/models/concerns/object_metadata.rb [moved from lib/object_metadata.rb with 97% similarity]
app/models/relation.rb
app/views/layouts/_header.html.erb
app/views/redactions/show.html.erb
app/views/users/_contact.html.erb
app/views/users/blocked.html.erb
config/environments/production.rb
config/environments/test.rb
config/initializers/r2.rb
config/locales/ar.yml
config/locales/be-Tarask.yml
config/locales/cs.yml
config/locales/da.yml
config/locales/diq.yml
config/locales/en.yml
config/locales/eo.yml
config/locales/fa.yml
config/locales/gl.yml
config/locales/lv.yml
config/locales/nl.yml
config/locales/pt-PT.yml
config/locales/sr.yml
config/locales/th.yml
config/locales/tr.yml
db/migrate/20181031113522_create_delayed_jobs.rb [new file with mode: 0644]
db/structure.sql
lib/classic_pagination/pagination.rb
lib/diff_reader.rb
lib/tasks/auto_annotate_models.rake
test/abilities/abilities_test.rb [new file with mode: 0644]
test/abilities/capability_test.rb [new file with mode: 0644]
test/controllers/amf_controller_test.rb
test/controllers/changeset_controller_test.rb
test/controllers/diary_entry_controller_test.rb
test/controllers/messages_controller_test.rb
test/controllers/notes_controller_test.rb
test/controllers/users_controller_test.rb
test/integration/user_creation_test.rb
test/models/relation_test.rb
test/test_helper.rb

index 29f21fde6f1178be3dd239791da197b071f89b44..761478b563baaec90676ac4ae7a9d35edd41e271 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -7,4 +7,4 @@ Kai Krueger <kakrueger@gmail.com> <kai@aiputerlx.(none)>
 Michael Glanznig <nebulon42@yandex.com>
 Petr Kadlec <mormegil@centrum.cz>
 Richard Fairhurst <richard@systemeD.net> <richard@systemed.net>
-Simon Poole <simon@poole.ch> <simon@rails-dev.poole.ch>
+Simon Poole <simon@poole.ch> <simon@rails-dev.poole.ch> <simonpoole@users.noreply.github.com>
index 8fc701cb3b7f9797cf67eba47fad086086d4b1a6..7d2c583eb73c4ebff19e52adc3367559e83757c2 100644 (file)
@@ -19,7 +19,7 @@ Lint/AssignmentInCondition:
     - 'app/helpers/application_helper.rb'
     - 'app/helpers/browse_helper.rb'
     - 'app/models/client_application.rb'
-    - 'app/models/notifier.rb'
+    - 'app/mailers/notifier.rb'
     - 'lib/nominatim.rb'
     - 'lib/osm.rb'
     - 'script/deliver-message'
@@ -32,7 +32,7 @@ Lint/HandleExceptions:
 
 # Offense count: 692
 Metrics/AbcSize:
-  Max: 280
+  Max: 283
 
 # Offense count: 40
 # Configuration parameters: CountComments, ExcludedMethods.
@@ -48,7 +48,7 @@ Metrics/BlockNesting:
 # Offense count: 63
 # Configuration parameters: CountComments.
 Metrics/ClassLength:
-  Max: 1795
+  Max: 1801
 
 # Offense count: 72
 Metrics/CyclomaticComplexity:
index 8ce7f5f305b317e36df70fe404bd68a2a87e110a..3b56d2b4b666af3b77fb9df25838a6259b0def03 100644 (file)
@@ -1,7 +1,7 @@
 sudo: false
 language: ruby
 rvm:
-  - 2.3.1
+  - 2.3.3
 cache: bundler
 addons:
   postgresql: 9.5
diff --git a/Gemfile b/Gemfile
index 9ba2703134d5d9b9bf8e5c47904c188396a762e7..05bfc6cbd3e6d14ea36f335a468cf6767038de70 100644 (file)
--- a/Gemfile
+++ b/Gemfile
@@ -45,7 +45,9 @@ gem "image_optim_rails"
 
 # Load rails plugins
 gem "actionpack-page_caching"
+gem "cancancan"
 gem "composite_primary_keys", "~> 11.0.0"
+gem "delayed_job_active_record"
 gem "dynamic_form"
 gem "http_accept_language", "~> 2.0.0"
 gem "i18n-js", ">= 3.0.0"
index 76a31e169e59a8c4aacd58ef738f2de056957302..72f769929033edf0790dbfe20be7567cfda32b40 100644 (file)
@@ -21,7 +21,7 @@ GEM
       rack-test (>= 0.6.3)
       rails-dom-testing (~> 2.0)
       rails-html-sanitizer (~> 1.0, >= 1.0.2)
-    actionpack-page_caching (1.1.0)
+    actionpack-page_caching (1.1.1)
       actionpack (>= 4.0.0, < 6)
     actionview (5.2.0)
       activesupport (= 5.2.0)
@@ -66,6 +66,7 @@ GEM
     bootsnap (1.3.2)
       msgpack (~> 1.0)
     builder (3.2.3)
+    cancancan (2.1.3)
     canonical-rails (0.2.4)
       rails (>= 4.1, < 5.3)
     capybara (2.18.0)
@@ -97,8 +98,13 @@ GEM
     crack (0.4.3)
       safe_yaml (~> 1.0.0)
     crass (1.0.4)
-    dalli (2.7.8)
+    dalli (2.7.9)
     debug_inspector (0.0.3)
+    delayed_job (4.1.5)
+      activesupport (>= 3.0, < 5.3)
+    delayed_job_active_record (4.1.3)
+      activerecord (>= 3.0, < 5.3)
+      delayed_job (>= 3.0, < 5)
     docile (1.3.1)
     dynamic_form (1.1.4)
     erubi (1.7.1)
@@ -109,7 +115,7 @@ GEM
     factory_bot_rails (4.11.1)
       factory_bot (~> 4.11.1)
       railties (>= 3.0.0)
-    faraday (0.12.2)
+    faraday (0.15.3)
       multipart-post (>= 1.2, < 3)
     ffi (1.9.25)
     fspath (3.1.0)
@@ -122,9 +128,9 @@ GEM
     http_accept_language (2.0.5)
     i18n (0.9.5)
       concurrent-ruby (~> 1.0)
-    i18n-js (3.0.11)
+    i18n-js (3.1.0)
       i18n (>= 0.6.6, < 2)
-    image_optim (0.26.2)
+    image_optim (0.26.3)
       exifr (~> 1.2, >= 1.2.2)
       fspath (~> 3.0)
       image_size (>= 1.5, < 3)
@@ -160,14 +166,14 @@ GEM
       rb-inotify (~> 0.9, >= 0.9.7)
       ruby_dep (~> 1.2)
     logstash-event (1.2.02)
-    logstasher (1.2.2)
+    logstasher (1.3.0)
       activesupport (>= 4.0)
       logstash-event (~> 1.2.0)
       request_store
-    loofah (2.2.2)
+    loofah (2.2.3)
       crass (~> 1.0.2)
       nokogiri (>= 1.5.9)
-    mail (2.7.0)
+    mail (2.7.1)
       mini_mime (>= 0.1.1)
     marcel (0.3.3)
       mimemagic (~> 0.3.2)
@@ -184,19 +190,19 @@ GEM
     multi_xml (0.6.0)
     multipart-post (2.0.0)
     nio4r (2.3.1)
-    nokogiri (1.8.4)
+    nokogiri (1.8.5)
       mini_portile2 (~> 2.3.0)
-    nokogumbo (1.5.0)
-      nokogiri
+    nokogumbo (2.0.0)
+      nokogiri (~> 1.8, >= 1.8.4)
     oauth (0.4.7)
     oauth-plugin (0.5.1)
       multi_json
       oauth (~> 0.4.4)
       oauth2 (>= 0.5.0)
       rack
-    oauth2 (1.4.0)
-      faraday (>= 0.8, < 0.13)
-      jwt (~> 1.0)
+    oauth2 (1.4.1)
+      faraday (>= 0.8, < 0.16.0)
+      jwt (>= 1.0, < 3.0)
       multi_json (~> 1.3)
       multi_xml (~> 0.5)
       rack (>= 1.2, < 3)
@@ -235,7 +241,7 @@ GEM
       mimemagic (~> 0.3.0)
       terrapin (~> 0.6.0)
     parallel (1.12.1)
-    parser (2.5.1.2)
+    parser (2.5.3.0)
       ast (~> 2.4.0)
     pg (0.21.0)
     poltergeist (1.18.1)
@@ -243,8 +249,8 @@ GEM
       cliver (~> 0.3.1)
       websocket-driver (>= 0.2.0)
     powerpack (0.1.2)
-    progress (3.4.0)
-    psych (3.0.2)
+    progress (3.5.0)
+    psych (3.0.3)
     public_suffix (3.0.3)
     puma (3.12.0)
     quad_tile (1.0.1)
@@ -300,36 +306,31 @@ GEM
     request_store (1.4.1)
       rack (>= 1.4)
     rinku (2.0.4)
-    rotp (3.3.1)
-    rubocop (0.59.1)
+    rotp (4.0.2)
+      addressable (~> 2.5)
+    rubocop (0.60.0)
       jaro_winkler (~> 1.5.1)
       parallel (~> 1.10)
       parser (>= 2.5, != 2.5.1.1)
       powerpack (~> 0.1)
       rainbow (>= 2.2.2, < 4.0)
       ruby-progressbar (~> 1.7)
-      unicode-display_width (~> 1.0, >= 1.0.1)
+      unicode-display_width (~> 1.4.0)
     ruby-openid (2.7.0)
     ruby-progressbar (1.10.0)
     ruby_dep (1.5.0)
     safe_yaml (1.0.4)
-    sanitize (4.6.6)
+    sanitize (5.0.0)
       crass (~> 1.0.2)
-      nokogiri (>= 1.4.4)
-      nokogumbo (~> 1.4)
-    sass (3.6.0)
-      sass-listen (~> 4.0.0)
-    sass-listen (4.0.0)
-      rb-fsevent (~> 0.9, >= 0.9.4)
-      rb-inotify (~> 0.9, >= 0.9.7)
-    sassc (1.12.1)
+      nokogiri (>= 1.8.0)
+      nokogumbo (~> 2.0)
+    sassc (2.0.0)
       ffi (~> 1.9.6)
-      sass (>= 3.3.0)
-    sassc-rails (1.3.0)
+      rake
+    sassc-rails (2.0.0)
       railties (>= 4.0.0)
-      sass
-      sassc (~> 1.9)
-      sprockets (> 2.11)
+      sassc (>= 2.0)
+      sprockets (> 3.0)
       sprockets-rails
       tilt
     secure_headers (6.0.0)
@@ -355,7 +356,7 @@ GEM
     thor (0.19.4)
     thread_safe (0.3.6)
     tilt (2.0.8)
-    tins (1.16.3)
+    tins (1.17.0)
     tzinfo (1.2.5)
       thread_safe (~> 0.1)
     uglifier (4.1.19)
@@ -363,7 +364,7 @@ GEM
     unicode-display_width (1.4.0)
     validates_email_format_of (1.6.3)
       i18n
-    vendorer (0.1.16)
+    vendorer (0.2.0)
     webmock (3.4.2)
       addressable (>= 2.3.6)
       crack (>= 0.3.2)
@@ -371,7 +372,7 @@ GEM
     websocket-driver (0.7.0)
       websocket-extensions (>= 0.1.0)
     websocket-extensions (0.1.3)
-    xpath (3.1.0)
+    xpath (3.2.0)
       nokogiri (~> 1.8)
 
 PLATFORMS
@@ -387,12 +388,14 @@ DEPENDENCIES
   bigdecimal (~> 1.1.0)
   binding_of_caller
   bootsnap (>= 1.1.0)
+  cancancan
   canonical-rails
   capybara (~> 2.13)
   coffee-rails (~> 4.2)
   composite_primary_keys (~> 11.0.0)
   coveralls
   dalli
+  delayed_job_active_record
   dynamic_form
   factory_bot_rails
   faraday
diff --git a/app/abilities/ability.rb b/app/abilities/ability.rb
new file mode 100644 (file)
index 0000000..f55f19e
--- /dev/null
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+class Ability
+  include CanCan::Ability
+
+  def initialize(user)
+    can [:index, :permalink, :edit, :help, :fixthemap, :offline, :export, :about, :preview, :copyright, :key, :id], :site
+    can [:index, :rss, :show, :comments], DiaryEntry
+    can [:search, :search_latlon, :search_ca_postcode, :search_osm_nominatim,
+         :search_geonames, :search_osm_nominatim_reverse, :search_geonames_reverse], :geocoder
+
+    if user
+      can :welcome, :site
+      can [:create, :edit, :comment, :subscribe, :unsubscribe], DiaryEntry
+      can [:new, :create], Report
+      can [:read, :read_one, :update, :update_one, :delete_one], UserPreference
+
+      if user.moderator?
+        can [:index, :show, :resolve, :ignore, :reopen], Issue
+        can :create, IssueComment
+      end
+
+      if user.administrator?
+        can [:hide, :hidecomment], [DiaryEntry, DiaryComment]
+        can [:index, :show, :resolve, :ignore, :reopen], Issue
+        can :create, IssueComment
+      end
+    end
+
+    # Define abilities for the passed in user here. For example:
+    #
+    #   user ||= User.new # guest user (not logged in)
+    #   if user.admin?
+    #     can :manage, :all
+    #   else
+    #     can :read, :all
+    #   end
+    #
+    # The first argument to `can` is the action you are giving the user
+    # permission to do.
+    # If you pass :manage it will apply to every action. Other common actions
+    # here are :read, :create, :update and :destroy.
+    #
+    # The second argument is the resource the user can perform the action on.
+    # If you pass :all it will apply to every resource. Otherwise pass a Ruby
+    # class of the resource.
+    #
+    # The third argument is an optional hash of conditions to further filter the
+    # objects.
+    # For example, here the user can only update published articles.
+    #
+    #   can :update, Article, :published => true
+    #
+    # See the wiki for details:
+    # https://github.com/CanCanCommunity/cancancan/wiki/Defining-Abilities
+  end
+end
diff --git a/app/abilities/capability.rb b/app/abilities/capability.rb
new file mode 100644 (file)
index 0000000..2a5c927
--- /dev/null
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class Capability
+  include CanCan::Ability
+
+  def initialize(token)
+    can [:read, :read_one], UserPreference if capability?(token, :allow_read_prefs)
+    can [:update, :update_one, :delete_one], UserPreference if capability?(token, :allow_write_prefs)
+  end
+
+  private
+
+  def capability?(token, cap)
+    token&.read_attribute(cap)
+  end
+end
index 56c4515d02a17b608b2f4eac86595c71443b8eb5..a16f7d85a56d4c13b8422c05034745753ab42f5c 100644 (file)
@@ -1324,11 +1324,11 @@ tr.turn:hover {
     #maxlat { margin-top: -1px; }
     #minlon {
       float: left;
-      margin-left: -1px;
+      /* no-r2 */ margin-left: -1px;
     }
     #maxlon {
       float: right;
-      margin-right: -1px;
+      /* no-r2 */ margin-right: -1px;
     }
     #minlat { margin-bottom: 0; }
   }
@@ -2314,6 +2314,7 @@ a.button {
     font-size: 13px;
     background: #e8e8e8;
     padding: 2px 3px;
+    white-space: pre-wrap;
 
     code {
       padding: 0;
index bd1995014882452fab08990432203104f5701381..1df6dd7d14cf41e1fad3ac04eb4512fe231eec13 100644 (file)
@@ -3,6 +3,8 @@ class ApplicationController < ActionController::Base
 
   protect_from_forgery :with => :exception
 
+  rescue_from CanCan::AccessDenied, :with => :deny_access
+
   before_action :fetch_body
   around_action :better_errors_allow_inline, :if => proc { Rails.env.development? }
 
@@ -22,7 +24,7 @@ class ApplicationController < ActionController::Base
       # don't allow access to any auth-requiring part of the site unless
       # the new CTs have been seen (and accept/decline chosen).
       elsif !current_user.terms_seen && flash[:skip_terms].nil?
-        flash[:notice] = t "user.terms.you need to accept or decline"
+        flash[:notice] = t "users.terms.you need to accept or decline"
         if params[:referer]
           redirect_to :controller => "users", :action => "terms", :referer => params[:referer]
         else
@@ -466,6 +468,29 @@ class ApplicationController < ActionController::Base
     raise
   end
 
+  def current_ability
+    # Add in capabilities from the oauth token if it exists and is a valid access token
+    if Authenticator.new(self, [:token]).allow?
+      Ability.new(current_user).merge(Capability.new(current_token))
+    else
+      Ability.new(current_user)
+    end
+  end
+
+  def deny_access(_exception)
+    if current_token
+      set_locale
+      report_error t("oauth.permissions.missing"), :forbidden
+    elsif current_user
+      set_locale
+      report_error t("application.permission_denied"), :forbidden
+    elsif request.get?
+      redirect_to :controller => "users", :action => "login", :referer => request.fullpath
+    else
+      head :forbidden
+    end
+  end
+
   private
 
   # extract authorisation credentials from headers, returns user = nil if none
index c03ed9056a0759277b1fda313132655299cb83f9..4ce205fd1513698dbfc9adeca3d5a48414a99ff0 100644 (file)
@@ -332,7 +332,7 @@ class ChangesetController < ApplicationController
 
     # Notify current subscribers of the new comment
     changeset.subscribers.visible.each do |user|
-      Notifier.changeset_comment_notification(comment, user).deliver_now if current_user != user
+      Notifier.changeset_comment_notification(comment, user).deliver_later if current_user != user
     end
 
     # Add the commenter to the subscribers if necessary
index 723fff17ec0e885c129087e003c343bfcf748bcd..70cb1654da8c9d0f7adf5b56197d482d81d54626 100644 (file)
@@ -3,11 +3,12 @@ class DiaryEntryController < ApplicationController
 
   before_action :authorize_web
   before_action :set_locale
-  before_action :require_user, :only => [:new, :edit, :comment, :hide, :hidecomment, :subscribe, :unsubscribe]
+
+  authorize_resource
+
   before_action :lookup_user, :only => [:show, :comments]
   before_action :check_database_readable
   before_action :check_database_writable, :only => [:new, :edit, :comment, :hide, :hidecomment, :subscribe, :unsubscribe]
-  before_action :require_administrator, :only => [:hide, :hidecomment]
   before_action :allow_thirdparty_images, :only => [:new, :edit, :index, :show, :comments]
 
   def new
@@ -65,7 +66,7 @@ class DiaryEntryController < ApplicationController
 
       # Notify current subscribers of the new comment
       @entry.subscribers.visible.each do |user|
-        Notifier.diary_comment_notification(@diary_comment, user).deliver_now if current_user != user
+        Notifier.diary_comment_notification(@diary_comment, user).deliver_later if current_user != user
       end
 
       # Add the commenter to the subscribers if necessary
@@ -215,6 +216,22 @@ class DiaryEntryController < ApplicationController
 
   private
 
+  # This is required because, being a default-deny system, cancancan
+  # _cannot_ tell you the reason you were denied access; and so
+  # the "nice" feedback presenting next steps can't be gleaned from
+  # the exception
+  ##
+  # for the hide actions, require that the user is a administrator, or fill out
+  # a helpful error message and return them to the user page.
+  def deny_access(exception)
+    if current_user && exception.action.in?([:hide, :hidecomment])
+      flash[:error] = t("users.filter.not_an_administrator")
+      redirect_to :action => "show"
+    else
+      super
+    end
+  end
+
   ##
   # return permitted diary entry parameters
   def entry_params
@@ -229,16 +246,6 @@ class DiaryEntryController < ApplicationController
     params.require(:diary_comment).permit(:body)
   end
 
-  ##
-  # require that the user is a administrator, or fill out a helpful error message
-  # and return them to the user page.
-  def require_administrator
-    unless current_user.administrator?
-      flash[:error] = t("user.filter.not_an_administrator")
-      redirect_to :action => "show"
-    end
-  end
-
   ##
   # decide on a location for the diary entry map
   def set_map_location
index 8d1acec759699d511058061152f5fcd966dad15c..0e4a7079e0e4c5e27608bf344767d529a4349e1f 100644 (file)
@@ -3,8 +3,8 @@ class IssueCommentsController < ApplicationController
 
   before_action :authorize_web
   before_action :set_locale
-  before_action :require_user
-  before_action :check_permission
+
+  authorize_resource
 
   def create
     @issue = Issue.find(params[:issue_id])
@@ -22,10 +22,12 @@ class IssueCommentsController < ApplicationController
     params.require(:issue_comment).permit(:body)
   end
 
-  def check_permission
-    unless current_user.administrator? || current_user.moderator?
+  def deny_access(_exception)
+    if current_user
       flash[:error] = t("application.require_moderator_or_admin.not_a_moderator_or_admin")
       redirect_to root_path
+    else
+      super
     end
   end
 
index ad38454f0650ba62ebd2dae40c1ab383c462c12a..8943f2d4aca695bd0ec2c6766586a70ffae95de1 100644 (file)
@@ -3,8 +3,9 @@ class IssuesController < ApplicationController
 
   before_action :authorize_web
   before_action :set_locale
-  before_action :require_user
-  before_action :check_permission
+
+  authorize_resource
+
   before_action :find_issue, :only => [:show, :resolve, :reopen, :ignore]
 
   def index
@@ -82,10 +83,12 @@ class IssuesController < ApplicationController
     @issue = Issue.find(params[:id])
   end
 
-  def check_permission
-    unless current_user.administrator? || current_user.moderator?
+  def deny_access(_exception)
+    if current_user
       flash[:error] = t("application.require_moderator_or_admin.not_a_moderator_or_admin")
       redirect_to root_path
+    else
+      super
     end
   end
 end
index 13a395da8fccfc20feb59174c36ec1178a36513a..c93c998f02655e60bee8ea202853005a0ee61d91 100644 (file)
@@ -29,7 +29,7 @@ class MessagesController < ApplicationController
       render :action => "new"
     elsif @message.save
       flash[:notice] = t ".message_sent"
-      Notifier.message_notification(@message).deliver_now
+      Notifier.message_notification(@message).deliver_later
       redirect_to :action => :inbox
     else
       render :action => "new"
index 95566a1a1a5ff179f1019dea52eed6d20235e8c7..9cdc38446ca5df7335528d34aeed3bbe5bbae4ad 100644 (file)
@@ -387,7 +387,7 @@ class NotesController < ApplicationController
     comment = note.comments.create!(attributes)
 
     note.comments.map(&:author).uniq.each do |user|
-      Notifier.note_comment_notification(comment, user).deliver_now if notify && user && user != current_user && user.visible?
+      Notifier.note_comment_notification(comment, user).deliver_later if notify && user && user != current_user && user.visible?
     end
   end
 end
index ef87a8699fe807884ec29d09d65a1064bf49a2fa..8087268193d9159932826415b33f9e31a05b131c 100644 (file)
@@ -3,7 +3,8 @@ class ReportsController < ApplicationController
 
   before_action :authorize_web
   before_action :set_locale
-  before_action :require_user
+
+  authorize_resource
 
   def new
     if required_new_report_params_present?
index efb77e2f52aad92574600d3d87082e3e1376bbe1..4b960e4e2b9682fd6e49036a25fff89093988bf0 100644 (file)
@@ -6,10 +6,11 @@ class SiteController < ApplicationController
   before_action :set_locale
   before_action :redirect_browse_params, :only => :index
   before_action :redirect_map_params, :only => [:index, :edit, :export]
-  before_action :require_user, :only => [:welcome]
   before_action :require_oauth, :only => [:index]
   before_action :update_totp, :only => [:index]
 
+  authorize_resource :class => false
+
   def index
     session[:location] ||= OSM.ip_location(request.env["REMOTE_ADDR"]) unless STATUS == :database_readonly || STATUS == :database_offline
   end
index 0aa2e8d523240c5f1eb3add8f6c978204bcab86f..915c847de4f221fc8a45662efa712d1ab79a5b3a 100644 (file)
@@ -2,8 +2,9 @@
 class UserPreferencesController < ApplicationController
   skip_before_action :verify_authenticity_token
   before_action :authorize
-  before_action :require_allow_read_prefs, :only => [:read_one, :read]
-  before_action :require_allow_write_prefs, :except => [:read_one, :read]
+
+  authorize_resource
+
   around_action :api_call_handle_error
 
   ##
index d18cf188cf669ef002fbc975f6f08d091f697d6f..016d7c87dd21c1501a453c1805b1a3130135786e 100644 (file)
@@ -107,7 +107,7 @@ class UsersController < ApplicationController
             successful_login(current_user)
           else
             session[:token] = current_user.tokens.create.token
-            Notifier.signup_confirm(current_user, current_user.tokens.create(:referer => referer)).deliver_now
+            Notifier.signup_confirm(current_user, current_user.tokens.create(:referer => referer)).deliver_later
             redirect_to :action => "confirm", :display_name => current_user.display_name
           end
         else
@@ -158,7 +158,7 @@ class UsersController < ApplicationController
 
       if user
         token = user.tokens.create
-        Notifier.lost_password(user, token).deliver_now
+        Notifier.lost_password(user, token).deliver_later
         flash[:notice] = t "users.lost_password.notice email on way"
         redirect_to :action => "login"
       else
@@ -339,7 +339,7 @@ class UsersController < ApplicationController
     if user.nil? || token.nil? || token.user != user
       flash[:error] = t "users.confirm_resend.failure", :name => params[:display_name]
     else
-      Notifier.signup_confirm(user, user.tokens.create).deliver_now
+      Notifier.signup_confirm(user, user.tokens.create).deliver_later
       flash[:notice] = t("users.confirm_resend.success", :email => user.email, :sender => SUPPORT_EMAIL).html_safe
     end
 
@@ -432,7 +432,7 @@ class UsersController < ApplicationController
           flash[:warning] = t "users.make_friend.already_a_friend", :name => @new_friend.display_name
         elsif friend.save
           flash[:notice] = t "users.make_friend.success", :name => @new_friend.display_name
-          Notifier.friend_notification(friend).deliver_now
+          Notifier.friend_notification(friend).deliver_later
         else
           friend.add_error(t("users.make_friend.failed", :name => @new_friend.display_name))
         end
@@ -735,7 +735,7 @@ class UsersController < ApplicationController
           flash.now[:notice] = t "users.account.flash update success confirm needed"
 
           begin
-            Notifier.email_confirm(user, user.tokens.create).deliver_now
+            Notifier.email_confirm(user, user.tokens.create).deliver_later
           rescue StandardError
             # Ignore errors sending email
           end
similarity index 89%
rename from lib/geo_record.rb
rename to app/models/concerns/geo_record.rb
index e02734ec909dc8064f78d2cf8e17455287939911..06049c2951b25876999cc7e3ee0fc070bacd97e6 100644 (file)
@@ -1,6 +1,8 @@
 require "delegate"
 
 module GeoRecord
+  extend ActiveSupport::Concern
+
   # Ensure that when coordinates are printed that they are always in decimal degrees,
   # and not e.g. 4.0e-05
   # Unfortunately you can't extend Numeric classes directly (e.g. `Coord < Float`).
@@ -19,9 +21,9 @@ module GeoRecord
   # the database.
   SCALE = 10000000
 
-  def self.included(base)
-    base.scope :bbox, ->(bbox) { base.where(OSM.sql_for_area(bbox)) }
-    base.before_save :update_tile
+  included do
+    scope :bbox, ->(bbox) { where(OSM.sql_for_area(bbox)) }
+    before_save :update_tile
   end
 
   # Is this node within -90 >= latitude >= 90 and -180 >= longitude >= 180
similarity index 78%
rename from lib/not_redactable.rb
rename to app/models/concerns/not_redactable.rb
index 6a57732963989841c89be951c60d941c52e1aed6..2d721530f133fb7f93b3c9c4d58dc4a11469b5de 100644 (file)
@@ -1,6 +1,6 @@
-require "osm"
-
 module NotRedactable
+  extend ActiveSupport::Concern
+
   def redacted?
     false
   end
similarity index 97%
rename from lib/object_metadata.rb
rename to app/models/concerns/object_metadata.rb
index c765df5264d6b749e59e178d847e618e84f40f6e..dcfde889ce83afdbc831185371cc4d7998123b5f 100644 (file)
@@ -1,4 +1,6 @@
 module ObjectMetadata
+  extend ActiveSupport::Concern
+
   def add_metadata_to_xml_node(el, osm, changeset_cache, user_display_name_cache)
     el["changeset"] = osm.changeset_id.to_s
     el["redacted"] = osm.redaction.id.to_s if osm.redacted?
index 202db12daa66479f379c4aeb84e49122279b1991..f55711a69bb75b060ae7a0ec61a120afbf852657 100644 (file)
@@ -384,7 +384,9 @@ class Relation < ActiveRecord::Base
         changed_members.collect { |type, _id, _role| type == "Relation" }
                        .inject(false) { |acc, elem| acc || elem }
 
-      update_members = if tags_changed || any_relations
+      # if the relation is being deleted tags_changed will be true and members empty
+      # so we need to use changed_members to create a correct bounding box
+      update_members = if visible && (tags_changed || any_relations)
                          # add all non-relation bounding boxes to the changeset
                          # FIXME: check for tag changes along with element deletions and
                          # make sure that the deleted element's bounding box is hit.
index e17c6a77be4cdfff11fc6444cdae7292b53515a4..946f95febf22f23aee9ba1391a70c2ab247be514 100644 (file)
@@ -54,7 +54,7 @@
       <li id="compact-secondary-nav" class="dropdown">
         <a class="dropdown-toggle" data-toggle="dropdown" href="#"><%= t 'layouts.more' %> <b class="caret"></b></a>
         <ul class="dropdown-menu">
-          <% if current_user and ( current_user.administrator? or current_user.moderator? ) %>
+          <% if can? :index, Issue %>
             <li class="<%= current_page_class(issues_path) %>">
               <%= link_to issues_path(:status => 'open') do %>
                 <%= open_issues_count %>
index 8ec72f3ac17cfd44a76ef8dc4ce88cf34efb8091..36b454188f09a88b9626319e42e68887823e3d0c 100644 (file)
@@ -7,10 +7,10 @@
   <b><%= t '.user' %></b>
   <%= link_to(@redaction.user.display_name, user_path(@redaction.user)) %>
 </p>
-<p class="richtext">
+<div class="richtext">
   <b><%= t '.description' %></b>
   <%= @redaction.description.to_html %>
-</p>
+</div>
 
 <% if current_user and current_user.moderator? %>
 <div class="buttons">
index bcc2faf354bf54f4a1987a20deefd4d815c3c0f4..ab56ce3e80a310f144611a47307d61e5bb6eb999 100644 (file)
       <% if @user.home_lon and @user.home_lat and contact.home_lon and contact.home_lat %>
         <% distance = @user.distance(contact) %>
         <% if distance < 1 %>
-          (<%= t 'user.show.m away', :count => (distance * 1000).round %>)
+          (<%= t 'users.show.m away', :count => (distance * 1000).round %>)
         <% else %>
-          (<%= t 'user.show.km away', :count => distance.round %>)
+          (<%= t 'users.show.km away', :count => distance.round %>)
         <% end %>
       <% end %>
     </p>
     <p>
       <% changeset = contact.changesets.first %>
       <% if changeset %>
-        <%= t('user.show.latest edit', :ago => t('user.show.ago', :time_in_words_ago => time_ago_in_words(changeset.created_at))) %>
+        <%= t('users.show.latest edit', :ago => t('users.show.ago', :time_in_words_ago => time_ago_in_words(changeset.created_at))) %>
         <% comment = changeset.tags['comment'].to_s != '' ? changeset.tags['comment'] : t('browse.no_comment') %>
         "<%= link_to(comment,
                             {:controller => 'browse', :action => 'changeset', :id => changeset.id},
index 93b4972d512809165efc12590f54d1e15796e4d9..d5be31ef649f278871bef192164d91f399424848 100644 (file)
@@ -1,10 +1,10 @@
 <% content_for :heading do %>
-  <h1><%= t 'user.new.title' %></h1>
+  <h1><%= t 'users.new.title' %></h1>
   <div class='header-illustration new-user-main'></div>
   <div class='header-illustration new-user-arm'></div>
 <% end %>
 
 <div class="message">
-  <h1><%= t 'user.new.no_auto_account_create' %></h1>
-  <h2><%= raw t 'user.new.contact_webmaster', :webmaster => "mailto:#{SUPPORT_EMAIL}" %></h2>
+  <h1><%= t 'users.new.no_auto_account_create' %></h1>
+  <h2><%= raw t 'users.new.contact_webmaster', :webmaster => "mailto:#{SUPPORT_EMAIL}" %></h2>
 </div>
index 4300321439f12f76ac040bf8b09b2c9886f534c0..9e15487ae4877fb80d9d1e0177958dbaee7efead 100644 (file)
@@ -99,4 +99,7 @@ Rails.application.configure do
 
   # Enable autoloading of dependencies.
   config.enable_dependency_loading = true
+
+  # Use delayed job to queue jobs in production.
+  config.active_job.queue_adapter = :delayed_job
 end
index e4652b7ec3ed8e52a19d7fd7e429e178b628e07f..38975deef664b54cb6332be608fb142fa7c3fe8a 100644 (file)
@@ -46,4 +46,7 @@ Rails.application.configure do
 
   # Raises error for missing translations
   config.action_view.raise_on_missing_translations = true
+
+  # Use the test adapter for ActiveJob during testing
+  config.active_job.queue_adapter = :test
 end
index 7fbb5c115002480f2f969303f7ca0b3fefbc9be5..4f951b30ce70b9dd8b49b0a2a083d31c47ebe405 100644 (file)
@@ -1,6 +1,6 @@
 require "r2"
 
-class R2ScssProcessor < Sprockets::ScssProcessor
+class R2ScssProcessor < SassC::Rails::ScssTemplate
   def self.call(input)
     output = super(input)
     data = R2.r2(output[:data])
index 9d579e991f9c98ba30621e457fd20e2b3268edb1..c0149910652894b2361499196d868c5c9521c1d3 100644 (file)
@@ -833,7 +833,7 @@ ar:
           cosmetics: بائع مستحضرات تجميل
           deli: دكان أطعمة شهية
           department_store: متجر متعدد الأقسام
-          discount: Ù\85Ø­Ù\84 Ø±Ø®ØµØ©
+          discount: Ù\85Ø­Ù\84 Ø¹Ù\86اصر Ø®ØµÙ\85
           doityourself: براعة منزلية
           dry_cleaning: تنظيف جاف
           electronics: متجر إلكترونيات
@@ -1167,14 +1167,14 @@ ar:
       subject: '[خريطة الشارع المفتوحة] طلب إعادة تعيين كلمة المرور'
     lost_password_plain:
       greeting: تحياتي،
-      hopefully_you: Ø´Ø®Øµ Ù\85ا (ربÙ\85ا Ø£Ù\86ت) Ø·Ù\84ب Ø¥Ø¹Ø§Ø¯Ø© ØªØ¹Ù\8aÙ\8aÙ\86 Ù\83Ù\84Ù\85Ø© Ø§Ù\84Ù\85رÙ\88ر Ù\84حساب openstreetmap.org
-        على عنوان البريد الإلكتروني هذا.
+      hopefully_you: Ø·Ø§Ù\84ب Ø´Ø®Øµ Ù\85ا (ربÙ\85ا Ø£Ù\86ت) Ø¨Ø¥Ø¹Ø§Ø¯Ø© ØªØ¹Ù\8aÙ\8aÙ\86 Ù\83Ù\84Ù\85Ø© Ø§Ù\84Ù\85رÙ\88ر Ø¹Ù\84Ù\89 حساب openstreetmap.org
+        لعنوان البريد الإلكتروني هذا.
       click_the_link: إذا كان هذا أنت، يُرجَى الضغط على الرابط أدناه لإعادة تعيين
         كلمة المرور.
     lost_password_html:
       greeting: تحياتي،
-      hopefully_you: Ø´Ø®Øµ Ù\85ا (ربÙ\85ا Ø£Ù\86ت) Ø·Ù\84ب Ø¥Ø¹Ø§Ø¯Ø© ØªØ¹Ù\8aÙ\8aÙ\86 Ù\83Ù\84Ù\85Ø© Ø§Ù\84Ù\85رÙ\88ر Ù\84حساب openstreetmap.org  Ø¹Ù\84Ù\89
-        عنوان البريد الإلكتروني هذا.
+      hopefully_you: Ø·Ø§Ù\84ب Ø´Ø®Øµ Ù\85ا (ربÙ\85ا Ø£Ù\86ت) Ø¨Ø¥Ø¹Ø§Ø¯Ø© ØªØ¹Ù\8aÙ\8aÙ\86 Ù\83Ù\84Ù\85Ø© Ø§Ù\84Ù\85رÙ\88ر Ø¹Ù\84Ù\89 Ø­Ø³Ø§Ø¨ openstreetmap.org
+        لعنوان البريد الإلكتروني هذا.
       click_the_link: إذا كان هذا أنت، يُرجَى الضغط على الرابط أدناه لإعادة تعيين
         كلمة المرور.
     note_comment_notification:
@@ -1300,16 +1300,14 @@ ar:
         الصور الجوية وأجهزة GPS والخرائط الميدانية ذات التقنية المنخفضة للتحقق من ذلك خريطة الشارع المفتوحة
         دقيقة وحديثة.
       community_driven_title: نابعة من المجتمع المحلي
-      community_driven_html: |-
-        مجتمع OpenStreetMap متنوع, عاطفي, ويزيد كل يوم.
-        يشمل المساهمون لدينا رسامي خرائط متحمسون, ومحترفي GIS, ومهندسين
-        تشغيل خوادم OSM ، والمساعدات الإنسانية للمناطق المتضررة من الكوارث ،
-        و أكثر من ذلك بكثير.
-        لمعرفة المزيد عن المجتمع ، انظر
-        <a href='https://blog.openstreetmap.org'></a>
-        <a href='%{diary_path}'></a>
-        <a href='https://blogs.openstreetmap.org/'></a>
-        و موقع <a href='https://www.osmfoundation.org/'></a>
+      community_driven_html: "مجتمع خريطة الشارع المفتوحة متنوع ومتحمس وينمو كل يوم،
+        \nيشمل المساهمون لدينا مصممي خرائط متحمسون، ومهنيي نظم المعلومات الجغرافية،
+        والمهندسون \nالذين يديرون خوادم خريطة الشارع المفتوحة، والمساعدات الإنسانية
+        للمناطق المتضررة من الكوارث،\nوغيرها الكثير،\nلمعرفة المزيد حول المجتمع; راجع
+        \n<a href='https://blog.openstreetmap.org'>مدونة خريطة الشارع المفتوحة</a>،\nو<a
+        href='%{diary_path}'> يوميات المستخدم</a>،\nو<a href='https://blogs.openstreetmap.org/'>مدونات
+        المجتمع</a>،\nوموقع the <a href='https://www.osmfoundation.org/'>مؤسسة خريطة
+        الشارع المفتوحة</a>."
       open_data_title: البيانات المفتوحة
       open_data_html: "خريطة الشارع المفتوحة <i>بيانات مفتوحة</i>: أنت حر في استخدامها
         لأي غرض\nطالما أنك تقوم بإحالة خريطة الشارع المفتوحة والمساهمين فيها، إذا
@@ -1331,61 +1329,55 @@ ar:
         english_link: النص الإنجليزي الأصلي
       native:
         title: حول هذه الصفحة
-        text: أنت تشاهد النسخة الإنجليزية لصفحة حقوق النشر. يمكنك الرجوع إلى %{native_link}٪
+        text: أنت تشاهد النسخة الإنجليزية لصفحة حقوق النشر، يمكنك الرجوع إلى %{native_link}٪
           {native_link} من هذه الصفحة أو يمكنك التوقف عن القراءة حول حقوق الطبع والنشر
-          و %{mapping_link}
+          و%{mapping_link}
         native_link: النسخة العربية
         mapping_link: ابدأ التخطيط
       legal_babble:
         title_html: حقوق النشر والترخيص
         intro_1_html: |-
-          OpenStreetMap <sup> <a href="#trademarks"> & reg؛ </a> </ sup> هو <i> بيانات مفتوحة </ i> ، مرخص بموجب <a
-          href = "https://opendatacommons.org/licenses/odbl/"> فتح البيانات
-          ترخيص Open Database License </a> (ODbL) بواسطة <a
-          href = "https://osmfoundation.org/"> مؤسسة OpenStreetMap </a> (OSMF).
-        intro_2_html: أنت حر في نسخ وتوزيع ونقل وتكييف بياناتنا، طالما كنت تأئتمن
-          خريطة الشارع المفتوحة والمساهمين فيها. إذا عدلت أو بنيت على البيانات المتوفرة
-          لدينا، فلا يحق لك توزيع النتيجة إلا تحت نفس الترخيص.<a href="http://opendatacommons.org/licenses/odbl/1.0/">
-          الكود القانوني الكامل</A> يشرح حقوقك ومسؤولياتك.
+          OpenStreetMap<sup><a href="#trademarks">&reg;</a></sup>  عبارة عن <i> بيانات مفتوحة</i>، ومرخصة تحت <a
+          href="https://opendatacommons.org/licenses/odbl/">رخصة قاعدة بيانات حرة</a> (ODbL)
+          بواسطة <a href="https://osmfoundation.org/">مؤسسة خريطة الشارع المفتوحة</a> (OSMF).
+        intro_2_html: "أنت حر في نسخ، وتوزيع، ونقل وتطويع بياناتنا، \nطالما أنك تقيد
+          خريطة الشارع المفتوحة\nوالمساهمين فيها، إذا عدلت أو بنيت على بياناتنا، \nفلا
+          يحق لك توزيع النتيجة إلا تحت نفس الترخيص، و\n<a href=\"https://opendatacommons.org/licenses/odbl/1.0/\">الكود
+          القانوني</a> الكامل يشرح حقوقك ومسؤولياتك."
         intro_3_html: |-
-          رسم الخرائط على الخريطة الخاص بنا ، ووثائقنا ،
-          مرخصة بموجب <a href="https://creativecommons.org/licenses/by-sa/2.0/"> Creative
-          الترخيص Attribution-ShareAlike 2.0 </a> (CC BY-SA).
-        credit_title_html: كيفية ائتمان OpenStreetMap
+          يتم  ترخيص رسم الخرائط في بلاط خرائطنا، ووثائقنا
+          بموجب ترخيص <a href="https://creativecommons.org/licenses/by-sa/2.0/">رخصة المشاع الإبداعي: النسبة-الترخيص بالمثل 2.0</a> (CC BY-SA).
+        credit_title_html: كيفية النسبة لخريطة الشارع المفتوحة
         credit_1_html: |-
           نطلب منك استخدام الائتمان &ldquo;&copy; OpenStreetMap
           contributors&rdquo;.
-        credit_2_html: |-
-          يجب أيضًا أن توضح أن البيانات متوفرة تحت Open
-          ترخيص قاعدة البيانات ، وإذا كان استخدام خريطتنا الخريطة ، فإن رسم الخرائط هو
-          مرخص كـ CC BY-SA. يمكنك القيام بذلك عن طريق ربط ل
-          <a href="https://www.openstreetmap.org/copyright"> صفحة حقوق الطبع والنشر هذه </a>.
-          بدلا من ذلك ، وكشرط إذا كنت تقوم بتوزيع OSM في
-          نموذج البيانات ، يمكنك تسمية والارتباط مباشرة إلى الترخيص (التراخيص). في وسائل الإعلام
-          حيث الروابط غير ممكنة (مثل الأعمال المطبوعة) ، فإننا نقترح عليك
-          توجيه القراء إلى openstreetmap.org (ربما عن طريق التوسع
-          "OpenStreetMap" إلى هذا العنوان الكامل) ، إلى opendatacommons.org ، و
-          إذا كان مناسبًا ، إلى creativecommons.org.
-        credit_3_html: 'للحصول على الخريطة الإلكترونية للتصفح، يجب أن يظهر الائتمان
+        credit_2_html: "يجب أيضا أن توضح أن البيانات متوفرة بموجب ترخيص\nقاعدة البيانات
+          المفتوحة، وفي حالة استخدام بلاط خرائطنا، يتم \nترخيص رسم الخرائط كـCC BY-SA،
+          يمكنك القيام بذلك عن طريق الربط بـ\n<a href=\"https://www.openstreetmap.org/copyright\">صفحة
+          حقوق الطبع والنشر هذه</a>.\nبدلا من ذلك، وكشرط إذا كنت تقوم بتوزيع خريطة
+          الشارع المفتوحة في \nنموذج بيانات، فيمكنك التسمية والربط مباشرةً إلى الترخيص(التراخيص).
+          في وسائل الإعلام\nحيث الروابط غير ممكنة (مثل الأعمال المطبوعة)، نقترح عليك
+          \nتوجيه القراء إلى openstreetmap.org (ربما عن طريق توسيع \n'OpenStreetMap'
+          إلى هذا العنوان الكامل)، وإلى opendatacommons.org، \nوإذا كان ذلك مناسبا،
+          إلى creativecommons.org."
+        credit_3_html: 'للحصول على الخريطة الإلكترونية للتصفح; يجب أن يظهر الائتمان
           في زاوية من الخريطة، مثلا:'
         attribution_example:
-          alt: مثال على كيفية إسناد OpenStreetMap على صفحة ويب
+          alt: مثال على كيفية إسناد خريطة الشارع المفتوحة على صفحة ويب
           title: مثال الإسناد
         more_title_html: معرفة المزيد
         more_1_html: |-
           اقرأ المزيد حول استخدام بياناتنا ، وكيفية اعتمادنا ، على <a
           href = "https://osmfoundation.org/Licence"> صفحة ترخيص OSMF </a>
-        more_2_html: |-
-          Ø¹Ù\84Ù\89 Ø§Ù\84رغÙ\85 Ù\85Ù\86 Ø£Ù\86 OpenStreetMap Ø¹Ø¨Ø§Ø±Ø© Ø¹Ù\86 Ø¨Ù\8aاÙ\86ات Ù\85Ù\81تÙ\88حة Ø\8c Ø¥Ù\84ا Ø£Ù\86Ù\86ا Ù\84ا Ù\86ستطÙ\8aع ØªÙ\88Ù\81Ù\8aر
-          خريطة API مجانية للجهات الخارجية.
-          Ø±Ø§Ø¬Ø¹ <a href="https://operations.osmfoundation.org/policies/api/"> Ø³Ù\8aاسة Ø§Ø³ØªØ®Ø¯Ø§Ù\85 Ù\88اجÙ\87Ø© Ø¨Ø±Ù\85جة Ø§Ù\84تطبÙ\8aÙ\82ات </a> Ø\8c
-          <a href="https://operations.osmfoundation.org/policies/tiles/"> سياسة استخدام الخريطة </a>
-          و <a href="https://operations.osmfoundation.org/policies/nominatim/"> سياسة استخدام Nominatim </a>.
+        more_2_html: "على الرغم من أن خريطة الشارع المفتوحة عبارة عن بيانات مفتوحة،
+          Ø¥Ù\84ا Ø£Ù\86Ù\87 Ù\84ا Ù\8aÙ\85Ù\83Ù\86Ù\86ا ØªÙ\88Ù\81Ù\8aر \nÙ\88اجÙ\87Ø© Ø¨Ø±Ù\85جة ØªØ·Ø¨Ù\8aÙ\82ات Ø®Ø±Ù\8aطة Ø­Ø±Ø© Ù\84Ù\84أطراÙ\81 Ø§Ù\84ثاÙ\84ثةØ\8c
+          \nراجع <a href=\"https://operations.osmfoundation.org/policies/api/\">سياسة
+          Ø§Ø³ØªØ®Ø¯Ø§Ù\85 Ù\88اجÙ\87Ø© Ø¨Ø±Ù\85جة Ø§Ù\84تطبÙ\8aÙ\82ات</a>Ø\8c\nÙ\88<a href=\"https://operations.osmfoundation.org/policies/tiles/\">سÙ\8aاسة
+          استخدام البلاط</a>،\nو<a href=\"https://operations.osmfoundation.org/policies/nominatim/\">سياسة
+          الاستخدام حسب الاسم</a> لدينا."
         contributors_title_html: المساهمين
-        contributors_intro_html: |-
-          مساهمينا هم الآلاف من الأفراد. نحن تشمل أيضا
-          بيانات مرخصة بشكل علني من وكالات الخرائط الوطنية
-          ومصادر أخرى ، من بينها:
+        contributors_intro_html: "مساهمونا هم آلاف الأفراد، نوفر أيضا \nبيانات مرخصة
+          بشكلٍ مفتوح من وكالات الخرائط الوطنية \nوغيرها من المصادر، من بينها:"
         contributors_at_html: |-
           <strong> النمسا </ strong>: يحتوي على بيانات من
           <a href="https://data.wien.gv.at/"> Stadt Wien </a> (under
@@ -1547,15 +1539,15 @@ ar:
             عن طريق السحب، أضف رسالتك، ثم انقر على "حفظ"، وسيتحرى مصممو الخرائط الآخرين.
       other_concerns:
         title: اهتمامات أخرى
-        explanation_html: |-
-          إذا كانت لديك مخاوف بشأن كيفية استخدام البيانات الخاصة بنا أو حول المحتويات ، فيرجى الرجوع إلى موقعنا
-          <a href='/copyright'> صفحة حقوق الطبع والنشر </a> لمزيد من المعلومات القانونية ، أو اتصل بالشكل المناسب
-          <a href='https://wiki.osmfoundation.org/wiki/Working_Groups'> مجموعة عمل OSMF </a>.
+        explanation_html: "إذا كانت لديك مخاوف بشأن كيفية استخدام بياناتنا أو حول
+          محتوياتها، فالرجاء الرجوع إلى \n<a href='/copyright'>صفحة حقوق الطبع والنشر
+          لدينا</a> لمزيد من المعلومات القانونية، أو الاتصال\n<a href='https://wiki.osmfoundation.org/wiki/Working_Groups'>بمجموعة
+          عمل مؤسسة خريطة الشارع المفتوحة</a>."
     help:
       title: الحصول على مساعدة
-      introduction: |-
-        يحتوي OpenStreetMap على العديد من الموارد للتعلم حول المشروع ، وطرح الأسئلة والإجابة عليها ،
-        والمشاركة في مناقشة وتوثيق مواضيع الخرائط.
+      introduction: "يحتوي خريطة الشارع المفتوحة على العديد من الموارد للتعلم حول
+        المشروع، وطرح الأسئلة والإجابة عليها، \nومناقشة مواضيع التخطيط وتوثيقها بشكل
+        تعاوني."
       welcome:
         url: أهلا بك.
         title: مرحبا بك في خريطة الشارع المفتوحة
@@ -1733,9 +1725,9 @@ ar:
         paragraph_1_html: إذا كنت تريد إصلاح مجرد شيء صغير وليس لديك الوقت للتسجيل
           ومعرفة كيفية التحرير، فإنه من السهل أن تضيف ملاحظة.
         paragraph_2_html: |-
-          ما عليك سوى الانتقال إلى <a href='%{map_url}'> الخريطة </a> والنقر على رمز الملاحظة:
-          <span class = 'icon note'> </ span>. سيضيف هذا علامة إلى الخريطة ، والتي يمكنك نقلها
-          Ø¹Ù\86 Ø·Ø±Ù\8aÙ\82 Ø§Ù\84سحب. Ø£Ø¶Ù\81 Ø±Ø³Ø§Ù\84تÙ\83 Ø\8c Ø«Ù\85 Ø§Ù\86Ù\82ر Ø¹Ù\84Ù\89 "Ø­Ù\81ظ" ، وسيتحرى مصممو الخرائط الآخرين.
+          ما عليك سوى الانتقال إلى <a href='%{map_url}'>الخريطة </a> والنقر على أيقونة الملاحظة:
+          <span class='icon note'></span>، سيضيف هذا علامة إلى الخريطة، والتي يمكنك نقلها
+          Ø¨Ø§Ù\84سحبØ\8c Ø£Ø¶Ù\81 Ø±Ø³Ø§Ù\84تÙ\83Ø\8c Ø«Ù\85 Ø§Ù\86Ù\82ر Ø¹Ù\84Ù\89 "Ø­Ù\81ظ"، وسيتحرى مصممو الخرائط الآخرين.
   traces:
     visibility:
       private: خصوصي (يظهر كمجهول الهوية ونقاط غير مرتبة)
@@ -1874,7 +1866,7 @@ ar:
       allow_read_prefs: يقرأ تفضيلات المستخدم.
       allow_write_prefs: عدّل تفضيلات المستخدم.
       allow_write_diary: إنشاء مدخلات يومية، تعليقات وإضافة أصدقاء.
-      allow_write_api: يعدّل الخريطة.
+      allow_write_api: تعديل الخريطة.
       allow_read_gpx: قراءة آثار جي بي أس الخاصة بك.
       allow_write_gpx: ارفع آثار جي بي أس.
       allow_write_notes: تعديل الملاحظات.
@@ -1893,13 +1885,13 @@ ar:
       missing: لم تسمح بالوصول إلى التطبيق لهذا المرفق
   oauth_clients:
     new:
-      title: Ø³Ø¬Ù\91Ù\90Ù\84 ØªØ·Ø¨Ù\8aÙ\82 جديد
+      title: Ø³Ø¬Ù\90Ù\91Ù\84 Ø·Ù\84با جديد
       submit: سجِّل
     edit:
-      title: Ø¹Ø¯Ù\91Ù\84 ØªØ·Ø¨Ù\8aÙ\82ك
+      title: Ø¹Ø¯Ù\84 Ø·Ù\84بك
       submit: تعديل
     show:
-      title: ØªÙ\81اصÙ\8aÙ\84 OAuth Ù\84Ù\84تطبÙ\8aÙ\82 %{app_name}
+      title: ØªÙ\81اصÙ\8aÙ\84 OAuth Ù\84Ù\80%{app_name}
       key: 'مفتاح المستهلك:'
       secret: 'سر المستهلك:'
       url: 'رابط طلب النموذج:'
@@ -1951,7 +1943,7 @@ ar:
     update:
       flash: تم تحديث معلومات العميل بنجاح
     destroy:
-      flash: Ø¯Ù\85Ù\91ر ØªØ³Ø¬Ù\8aÙ\84 Ø§Ù\84تطبÙ\8aÙ\82
+      flash: Ø¯Ù\8fÙ\85Ù\90Ù\91ر ØªØ³Ø¬Ù\8aÙ\84 ØªØ·Ø¨Ù\8aÙ\82 Ø§Ù\84عÙ\85Ù\8aÙ\84
   users:
     login:
       title: تسجيل الدخول
@@ -1965,15 +1957,15 @@ ar:
       register now: سجل حسابًا الآن
       with username: 'هل لديك بالفعل حساب خريطة الشارع المفتوحة؟ الرجاء الدخول باسم
         المستخدم وكلمة المرور الخاصين بك:'
-      with external: 'بدÙ\84ا Ù\85Ù\86 Ø°Ù\84Ù\83Ø\8c Ø§Ø³ØªØ®Ø¯Ù\85 Ø·Ø±Ù\81ا Ø¢Ø®Ø± Ù\84لدخول:'
-      new to osm: Ø¬Ø¯Ù\8aد Ù\84خرÙ\8aطة Ø§Ù\84شارع Ø§Ù\84Ù\85Ù\81تÙ\88حة ؟
+      with external: 'بدÙ\84ا Ù\85Ù\86 Ø°Ù\84Ù\83Ø\8c Ø§Ø³ØªØ®Ø¯Ù\85 Ø·Ø±Ù\81ا Ø«Ø§Ù\84ثا Ù\84تسجÙ\8aÙ\84 Ø§لدخول:'
+      new to osm: Ø¬Ø¯Ù\8aد Ù\81Ù\8a Ø®Ø±Ù\8aطة Ø§Ù\84شارع Ø§Ù\84Ù\85Ù\81تÙ\88حة؟
       to make changes: لإجراء تغييرات على بيانات خريطة الشارع المفتوحة; يجب أن يكون
         لديك حساب.
-      create account minute: Ø£Ù\86شئ Ø­Ø³Ø§Ø¨Ø§Ù\91. ØªØ­ØªØ§Ø¬ Ù\81Ù\82Ø· Ø¥Ù\84Ù\89 Ø¯Ù\82Ù\8aÙ\82Ø©.
-      no account: ليس لديك حسابا ؟
-      account not active: عذراً، حسابك غير نشط حتى الآن.<br />يُرجى إستخدام الرابط
-        Ø§Ù\84Ø°Ù\8a Ø§Ù\8fرسÙ\90Ù\84Ù\8e Ø¥Ù\84Ù\8aÙ\83 Ù\81Ù\89 Ø±Ø³Ø§Ù\84Ø© ØªØ£Ù\83Ù\8aد Ø§Ù\84برÙ\8aد Ø§Ù\84Ø¥Ù\84Ù\83ترÙ\88Ù\86Ù\8aØ\8c Ù\83Ù\85ا <a href="%{reconfirm}">Ù\8aÙ\8fÙ\85Ù\83Ù\86Ù\83
-        Ø·Ù\84ب Ø±Ø³Ø§Ù\84Ø© ØªØ£Ù\83Ù\8aد Ø¬Ø¯Ù\8aدة Ù\81Ù\89 Ø­Ø§Ù\84Ø© Ø¹Ø¯Ù\85 Ø¥ستلام الاولى</a>.
+      create account minute: Ø§Ù\86شئ Ø­Ø³Ø§Ø¨Ø§Ø\8c Ø¥Ù\86Ù\87ا ØªØ³ØªØºØ±Ù\82 Ø¯Ù\82Ù\8aÙ\82Ø© Ù\88احدة Ù\81Ù\82Ø·.
+      no account: ليس لديك حسابا؟
+      account not active: Ø¹Ø°Ø±Ø§Ù\8bØ\8c Ø­Ø³Ø§Ø¨Ù\83 ØºÙ\8aر Ù\86شط Ø­ØªÙ\89 Ø§Ù\84Ø¢Ù\86.<br />Ù\8aÙ\8fرجÙ\8eÙ\89 Ø¥Ø³ØªØ®Ø¯Ø§Ù\85 Ø§Ù\84رابط
+        الذي اُرسِلَ إليك فى رسالة تأكيد البريد الإلكتروني، كما <a href="%{reconfirm}">يمكنك
+        Ø·Ù\84ب Ø±Ø³Ø§Ù\84Ø© ØªØ£Ù\83Ù\8aد Ø¬Ø¯Ù\8aدة Ù\81Ù\89 Ø­Ø§Ù\84Ø© Ø¹Ø¯Ù\85 Ø§ستلام الاولى</a>.
       account is suspended: عذرا، تم تعليق حسابك بسبب نشاط مشبوه.<br />يُرجَى الاتصال
         ب<a href="%{webmaster}">webmaster</a> إذا كنت ترغب في مناقشة هذا.
       auth failure: آسف، لا يمكن الدخول بتلك التفاصيل.
@@ -1981,12 +1973,12 @@ ar:
       auth_providers:
         openid:
           title: تسجيل الدخول بOpenID
-          alt: تسجيل الدخول باستخدام OpenID URL
+          alt: تسجيل الدخول باستخدام مسار OpenID
         google:
-          title: قم بتسجيل الدخول عن طريق جوجل
+          title: تسجيل الدخول باستخدام جوجل
           alt: تسجيل الدخول ب Google OpenID
         facebook:
-          title: قم بتسجيل الدخول باستخدام الفيس بوك
+          title: تسجيل الدخول باستخدام فيس بوك
           alt: تسجيل الدخول بحساب فيسبوك
         windowslive:
           title: تسجيل الدخول عبر ويندوز لايف
@@ -1999,13 +1991,13 @@ ar:
           alt: سجل الدخول باستخدام حساب ويكيبيديا
         yahoo:
           title: تسجيل الدخول بياهو
-          alt: تسجيل الدخول ب Yahoo OpenID
+          alt: تسجيل الدخول بـYahoo OpenID
         wordpress:
           title: تسجيل الدخول بووردبريس
-          alt: تسجيل الدخول ب Wordpress OpenID
+          alt: تسجيل الدخول بـWordpress OpenID
         aol:
           title: تسجيل الدخول بإيه أو إل
-          alt: تسجيل الدخول ب AOL OpenID
+          alt: تسجيل الدخول بـAOL OpenID
     logout:
       title: تسجيل الخروج
       heading: الخروج من خريطة الشارع المفتوحة
@@ -2015,19 +2007,19 @@ ar:
       heading: أنسيت كلمة المرور؟
       email address: 'عنوان البريد الإلكتروني:'
       new password button: أعد ضبط كلمة السر
-      help_text: أدخل عنوان البريد الإلكتروني الذي استخدمته للتسجيل ، وسوف نرسل عليه
-        رابط يمكنك استخدامه لإعادة تعيين كلمة المرور.
+      help_text: أدخل عنوان البريد الإلكتروني الذي استخدمته للتسجيل، وسوف نرسل عليه
+        رابطا يمكنك استخدامه لإعادة تعيين كلمة المرور.
       notice email on way: نأسف لأنك أضعتها :-( ولكن هناك رسالة إلكترونية في طريقها
         إليك ستمكنك من إعادة تعيينها قريبًا.
-      notice email cannot find: تعذّر إيجاد عنوان البريد الإلكتروني، نحن آسفون.
+      notice email cannot find: معذرةً، تعذر إيجاد عنوان البريد الإلكتروني.
     reset_password:
       title: إعادة ضبط كلمة السر
       heading: إعادة تعيين كلمة المرور %{user}
       password: 'كلمة السر:'
-      confirm password: 'Ø£Ù\83Ù\91د Ù\83Ù\84Ù\85Ø© Ø§Ù\84Ù\85رÙ\88ر:'
+      confirm password: 'تأÙ\83Ù\8aد Ù\83Ù\84Ù\85Ø© Ø§Ù\84سر:'
       reset: أعد ضبط كلمة السر
-      flash changed: كلمة المرور الخاصة بك قد تغيرت.
-      flash token bad: لم نجد هذا النموذج، تحقق من الرابط ربما؟
+      flash changed: كلمة مرورك قد تغيرت.
+      flash token bad: لم نجد هذا النموذج، تحقق من المسار ربما؟
     new:
       title: أنشئ حسابا
       no_auto_account_create: للأسف نحن غير قادرين في الوقت الحالي على إنشاء حساب
@@ -2038,68 +2030,68 @@ ar:
         header: حًرَّة وقابلة للتحرير
         html: |-
           <p>على عكس الخرائط الأخرى تماما، يتم إنشاء خريطة الشارع المفتوحة من قبل الناس مثلك، وهي حرة ويمكن لأي أحد الإصلاح والتحديث والتنزيل والاستخدام.</p>
-           <P> أنشىء حسابا لبدء المساهمة.سنقوم بإرسال بريد إلكتروني لتأكيد حسابك.</p>
+          <P> أنشىء حسابا لبدء المساهمة.سنقوم بإرسال بريد إلكتروني لتأكيد حسابك.</p>
       license_agreement: عند تأكيد حسابك ستحتاج إلى الموافقة على <a href="HTTPS://www.osmfoundation.org/wiki/License/Contributor_Terms">شروط
         المساهم</a>.
       email address: 'عنوان البريد الإلكتروني:'
       confirm email address: 'تأكيد عنوان البريد الإلكتروني:'
-      not displayed publicly: Ù\84ا Ù\8aعرض Ø¹Ù\84Ù\86Ù\8bا (اÙ\86ظر <a href="http://wiki.openstreetmap.org/wiki/Privacy_Policy"
-        title="ويكي سياسة الخصوصية المتضمنة قسم عن عناوين البريد الإلكتروني">سياسة
-        الخصوصية</a>)
-      display name: 'اسم المستخدم:'
-      display name description: اسم المستخدم الخاص بك الظاهر علنًا. يمكنك تغيير هذه
-        التفضيلات في وقت لاحق.
+      not displayed publicly: Ù\84ا Ù\8aتÙ\85 Ø¹Ø±Ø¶ Ø¹Ù\86Ù\88اÙ\86Ù\83 Ø¨Ø´Ù\83Ù\84 Ø¹Ø§Ù\85Ø\8c Ø±Ø§Ø¬Ø¹ <a href="https://wiki.osmfoundation.org/wiki/Privacy_Policy"
+        title="سياسة خصوصية OSMF بما في ذلك القسم عن عناوين البريد الإلكتروني ">سياسة
+        الخصوصية</a> لمزيد من المعلومات
+      display name: 'اسم العرض:'
+      display name description: اسم المستخدم الخاص بك الظاهر علنًا، يمكنك تغيير هذا
+        في التفضيلات في وقت لاحق.
       external auth: 'مصادقة طرف ثالث:'
       password: 'كلمة السر:'
       confirm password: 'تأكيد كلمة المرور:'
-      use external auth: 'بدÙ\84ا Ù\85Ù\86 Ø°Ù\84Ù\83Ø\8c Ø§Ø³ØªØ®Ø¯Ù\85 Ø·Ø±Ù\81ا Ø¢Ø®Ø± Ù\84لدخول:'
+      use external auth: 'بدÙ\84ا Ù\85Ù\86 Ø°Ù\84Ù\83Ø\8c Ø§Ø³ØªØ®Ø¯Ù\85 Ø·Ø±Ù\81ا Ø«Ø§Ù\84ثا Ù\84تسجÙ\8aÙ\84 Ø§لدخول:'
       auth no password: مع مصادقة طرف ثالث كلمة السر غير مطلوبة، ولكن بعض الأدوات
         إضافية أو الخادم قد لا تزال تحتاج إلى واحدة.
       continue: أنشئ حسابا
       terms accepted: نشكرك على قبول شروط المساهم الجديدة!
-      terms declined: نحن نأسف أن كنت قد قررت عدم قبول شروط المساهمة الجديدة. لمزيد
-        من المعلومات، يرجى الاطلاع على <a href="%{url}">صفحة الويكي هذه</a>.
+      terms declined: نحن نأسف أن كنت قد قررت عدم قبول شروط المساهمة الجديدة، لمزيد
+        من المعلومات; يُرجَى الاطلاع على <a href="%{url}">صفحة الويكي هذه</a>.
       terms declined url: https://wiki.openstreetmap.org/wiki/Contributor_Terms_Declined
     terms:
       title: 'شروط المساهم:'
       heading: 'شروط المساهم:'
-      read and accept: يرجى قراءة الاتفاقية أدناه والضغط على زر الموافقة لتأكيد قبول
-        شروط هذا الاتفاق على مشاركاتك الموجودة حاليًا والمستقبلية.
+      read and accept: تُرجَى قراءة الاتفاقية أدناه والضغط على زر الموافقة لتأكيد
+        قبول شروط هذا الاتفاق على مشاركاتك الموجودة والمستقبلية.
       consider_pd: وبالإضافة إلى الاتفاقية أعلاه، أريد أن تكون مساهماتي ملكية عامة.
       consider_pd_why: ما هذا؟
       consider_pd_why_url: https://www.osmfoundation.org/wiki/License/Why_would_I_want_my_contributions_to_be_public_domain
-      guidance: 'معلومات للمساعدة في فهم هذه المصطلحات: <a href="%{summary}"> ملخص
-        قابل للقراءة بالإنسان </a> وبعض <a href="%{translations}"> ترجمة غير رسمية
-        </a>'
+      guidance: 'معلومات للمساعدة في فهم هذه المصطلحات: <a href="%{summary}">ملخص
+        قابل للقراءة بواسطة الإنسان </a> وبعض <a href="%{translations}">ترجمات غير
+        رسمية</a>'
       agree: أوافق
       declined: https://wiki.openstreetmap.org/wiki/Contributor_Terms_Declined
-      decline: Ø§Ù\86Ø®Ù\81اض
+      decline: Ø£Ø±Ù\81ض
       you need to accept or decline: الرجاء القراءة ومن ثم قبول أو رفض شروط المساهمة
         الجديدة للمتابعة.
-      legale_select: 'اÙ\84رجاء Ø§Ø®ØªÙ\8aار Ø¨Ù\84د Ø§Ù\84Ø¥Ù\82اÙ\85Ø©:'
+      legale_select: 'بلد الإقامة:'
       legale_names:
         france: فرنسا
         italy: إيطاليا
         rest_of_world: بقية العالم
     no_such_user:
-      title: Ù\85ستخدÙ\85 ØºÙ\8aر Ù\85Ù\88جÙ\88د
+      title: Ù\84ا Ù\8aÙ\88جد Ù\85ستخدÙ\85 Ù\83Ù\87ذا
       heading: المستخدم %{user} غير موجود
-      body: عذرًا، لا يوجد مستخدم بالاسم %{user}. يرجى تدقيق الاسم، أو ربما يكون الرابط
-        الذي تم النقر عليه خاطئ.
+      body: عذرًا، لا يوجد مستخدم بالاسم %{user}; يُرجَى تدقيق الاسم، أو ربما يكون
+        Ø§Ù\84رابط Ø§Ù\84Ø°Ù\8a ØªÙ\85 Ø§Ù\84Ù\86Ù\82ر Ø¹Ù\84Ù\8aÙ\87 Ø®Ø§Ø·Ø¦.
       deleted: تم حذفه
     show:
       my diary: اليوميات
       new diary entry: مدخلة يومية جديدة
-      my edits: Ø§Ù\84Ù\85Ù\8fساÙ\87Ù\85ات
+      my edits: ØªØ¹Ø¯Ù\8aÙ\84اتÙ\8a
       my traces: آثاري
       my notes: ملاحظاتي
       my messages: رسائلي
       my profile: ملفي الشخصي
-      my settings: Ø§Ù\84إعدادات
+      my settings: Ø¥Ø¹Ø¯Ø§Ø¯Ø§ØªÙ\8a
       my comments: تعليقاتي
       oauth settings: "\uFEFFإعدادات oauth"
-      blocks on me: Ø§Ù\84عرÙ\82Ù\84ات Ø¹Ù\84ي
-      blocks by me: Ø§Ù\84عرÙ\82Ù\84ات بواسطتي
+      blocks on me: Ø¹Ù\85Ù\84Ù\8aات Ù\85Ù\86عي
+      blocks by me: Ø¹Ù\85Ù\84Ù\8aات Ø§Ù\84Ù\85Ù\86ع بواسطتي
       send message: إرسل رسالة
       diary: يومية
       edits: مساهمات
@@ -2108,57 +2100,58 @@ ar:
       remove as friend: إلغاء الصداقة
       add as friend: أضف كصديق
       mapper since: 'مُخطط منذ:'
-      ago: (%{time_in_words_ago})
+      ago: منذ %{time_in_words_ago}
       ct status: 'شروط المساهم:'
       ct undecided: متردد
       ct declined: مرفوض
-      ct accepted: مقبول %{ago} سابقاً
+      ct accepted: مقبول منذ %{ago}
       latest edit: 'آخر تغيير %{ago}:'
       email address: 'عنوان البريد الإلكتروني:'
-      created from: 'Ø£Ù\8fÙ\86Ø´Ù\89Ø¡ من:'
+      created from: 'Ø£Ù\8fÙ\86Ø´Ù\90ئ من:'
       status: 'الحالة:'
       spam score: 'نتيجة السخام:'
       description: الوصف
-      user location: الموقع
-      if set location: عين موقعك على صفحة %{settings_link} لرؤية المستخدمون القريبون
+      user location: موقع المستخدم
+      if set location: قم بتعيين موقعك على صفحة %{settings_link} لرؤية المستخدمون
+        القريبين
       settings_link_text: إعدادات
       my friends: أصدقائي
       no friends: لم تقم بإضافة أي أصدقاء بعد.
       km away: على بعد %{count}كم
       m away: على بعد %{count}متر
-      nearby users: 'مستخدمين أيضًا بالجوار:'
+      nearby users: مستخدمون آخرون قريبون
       no nearby users: لا يوجد بعد المزيد من المستخدمين أفصحوا عن تخطيطهم بالجوار.
       role:
         administrator: هذا المستخدم إداري
-        moderator: Ù\87ذا Ø§Ù\84Ù\85ستخدÙ\85 Ù\88سÙ\8aØ·
+        moderator: Ù\87ذا Ø§Ù\84Ù\85ستخدÙ\85 Ù\85شرÙ\81
         grant:
           administrator: منح وصول إداري
-          moderator: Ù\85Ù\86Ø­ Ù\88صÙ\88Ù\84 Ù\88سÙ\8aØ·
+          moderator: Ù\85Ù\86Ø­ Ù\88صÙ\88Ù\84 Ù\85شرÙ\81
         revoke:
-          administrator: Ø§Ø¨Ø·ل وصول إداري
-          moderator: Ø§Ø¨Ø·Ù\84 Ù\88صÙ\88Ù\84 Ù\88سÙ\8aØ·
-      block_history: Ø§Ù\84عرÙ\82Ù\84ات المفعلة
-      moderator_history: ' العرقلات المعطاة'
+          administrator: Ø¥Ø¨Ø·Ø§ل وصول إداري
+          moderator: Ø¥Ø¨Ø·Ø§Ù\84 Ù\88صÙ\88Ù\84 Ù\85شرÙ\81
+      block_history: Ø¹Ù\85Ù\84Ù\8aات Ø§Ù\84Ù\85Ù\86ع المفعلة
+      moderator_history: عمليات المنع المعطاة
       comments: التعليقات
       create_block: امنع هذا المستخدم
-      activate_user: نشّط هذا المستخدم
-      deactivate_user: Ø§Ø­Ø°Ù\81 هذا المستخدم
+      activate_user: Ù\86Ø´Ù\90Ù\91Ø· Ù\87ذا Ø§Ù\84Ù\85ستخدÙ\85
+      deactivate_user: ØªØ¹Ø·Ù\8aÙ\84 هذا المستخدم
       confirm_user: تأكيد هذا المستخدم
       hide_user: اخفِ هذا المستخدم
       unhide_user: أظهر هذا المستخدم
       delete_user: احذف هذا المستخدم
-      confirm: Ø£Ù\83Ù\91د
-      friends_changesets: تصفح كل حزم التغييرات من قبل الأصدقاء
-      friends_diaries: تصفح جميع مدخلات مدونات الأصدقاء
-      nearby_changesets: ØªØµÙ\81Ø­ Ù\83Ù\84 Ø­Ø²Ù\85 Ø§Ù\84تغÙ\8aÙ\8aرات Ù\85Ù\86 Ù\82بÙ\84 Ø§Ù\84Ù\85ستخدÙ\85Ù\8aÙ\86 Ø§Ù\84Ù\82رÙ\8aبÙ\88ن
-      nearby_diaries: ØªØµÙ\81Ø­ Ø¬Ù\85Ù\8aع Ù\85دخÙ\84ات Ù\85دÙ\88Ù\86ات Ø§Ù\84Ù\85ستخدÙ\85Ù\8aÙ\86 Ù\81Ù\8a Ø§Ù\84Ù\82رÙ\8aبÙ\88ن
-      report: أبلغ عن هذه المستخدم
+      confirm: ØªØ£Ù\83Ù\8aد
+      friends_changesets: مجموعات تغييرات الأصدقاء
+      friends_diaries: مدخلات مدونات الأصدقاء
+      nearby_changesets: Ø­Ø²Ù\85 ØªØºÙ\8aÙ\8aرات Ø§Ù\84Ù\85ستخدÙ\85Ù\8aÙ\86 Ø§Ù\84Ù\82رÙ\8aبÙ\8aن
+      nearby_diaries: Ø¥Ø¯Ø®Ø§Ù\84ات Ù\8aÙ\88Ù\85Ù\8aات Ø§Ù\84Ù\85ستخدÙ\85Ù\8aÙ\86 Ø§Ù\84Ù\82رÙ\8aبÙ\8aن
+      report: أبلغ عن هذا المستخدم
     popup:
       your location: مكانك
       nearby mapper: مخطط بالجوار
       friend: صديق
     account:
-      title: Ø¹Ø¯Ù\91Ù\84 Ø§Ù\84حساب
+      title: عدل الحساب
       my settings: إعداداتي
       current email address: 'عنوان البريد الإلكرتروني الحالي:'
       new email address: 'عنوان البريد الإلكتروني الجديد:'
@@ -2166,33 +2159,33 @@ ar:
       external auth: 'مصادقة خارجية:'
       openid:
         link: http://wiki.openstreetmap.org/wiki/OpenID
-        link text: ما هذا ؟
+        link text: ما هذا؟
       public editing:
         heading: 'تعديل عام:'
-        enabled: Ù\85Ù\81عÙ\91Ù\84. غير مجهول ويمكنك تعديل البيانات.
+        enabled: Ù\85Ù\81عÙ\8eÙ\91Ù\84Ø\8c غير مجهول ويمكنك تعديل البيانات.
         enabled link: http://wiki.openstreetmap.org/wiki/Anonymous_edits
         enabled link text: ما هذا؟
         disabled: مُعطل ولا يمكن تعديل البيانات، جميع التعديلات السابقة مجهولة الهوية.
         disabled link text: لماذا لا أستطيع التعديل؟
       public editing note:
         heading: تعديل عام
-        text: حاليًا تعديلاتك تظهر بشكل مجهول ولا يمكن للناس إرسال رسائل لك أو رؤية
-          موقعك. لإظهار ما قمت بتعديله وللسماح للناس بالاتصال بك من خلال الموقع، انقر
-          Ø¹Ù\84Ù\89 Ø§Ù\84زر Ø£Ø¯Ù\86اÙ\87. <b>Ù\85Ù\86Ø° Ø§Ù\84تغÙ\8aÙ\8aر Ø¥Ù\84Ù\89 Ø§Ù\84Ø£Ù\8a Ø¨Ù\8a Ø£Ù\8a 0.6Ø\8c Ù\81Ù\82Ø· Ø§Ù\84Ù\85ستخدÙ\85Ù\8aÙ\86 Ø§Ù\84عÙ\84Ù\86Ù\8aÙ\8aÙ\86
-          يمكنه تحرير بيانات الخريطة</b>. (<a href="http://wiki.openstreetmap.org/wiki/Anonymous_edits">لمعرفة
-          السبب</a>). <ul><li>عنوانك البريدي لن يكشف به علنّا.</li><li>هذا الإجراء
-          Ù\84ا Ù\8aÙ\85Ù\83Ù\86 Ø¹Ù\83سÙ\87 Ù\88جÙ\85Ù\8aع Ø§Ù\84Ù\85ستخدÙ\85Ù\8aÙ\86 Ø§Ù\84جدÙ\8aد Ø¹Ù\84Ù\86Ù\8aÙ\8aÙ\86 Ø¨Ø´Ù\83Ù\84 Ø§Ù\81تراضÙ\8a.</li></ul>
+        text: في الوقت الحالي، تعديلاتك مجهولة الهوية ولا يمكن للأشخاص إرسال رسائل
+          إليك أو الاطلاع على موقعك، لإظهار ما قمت بتحريره والسماح للأشخاص بالاتصال
+          Ø¨Ù\83 Ø¹Ø¨Ø± Ù\85Ù\88Ù\82ع Ø§Ù\84Ù\88Ù\8aب; Ø§Ù\86Ù\82ر Ù\81Ù\88Ù\82 Ø§Ù\84زر Ø£Ø¯Ù\86اÙ\87<b>Ù\85Ù\86Ø° ØªØºÙ\8aÙ\8aر Ù\88اجÙ\87Ø© Ø¨Ø±Ù\85جة Ø§Ù\84تطبÙ\8aÙ\82ات
+          0.6، لا يمكن سوى للمستخدمين العموميين تعديل بيانات الخريطة</b>. (<a href="https://wiki.openstreetmap.org/wiki/Anonymous_edits">اكتشف
+          السبب</a>).<ul><li>لن يتم الكشف عن عنوان بريدك الإلكتروني من خلال جعله عاما.</li><li>لا
+          Ù\8aÙ\85Ù\83Ù\86 Ø¹Ù\83س Ù\87ذا Ø§Ù\84إجراء Ù\88أصبح Ø¬Ù\85Ù\8aع Ø§Ù\84Ù\85ستخدÙ\85Ù\8aÙ\86 Ø§Ù\84جدد Ø¹Ø§Ù\85Ù\8aÙ\86 Ø§Ù\81تراضÙ\8aا.</li></ul>
       contributor terms:
         heading: 'شروط المساهم:'
-        agreed: لقد وافقتَ على شروط المساهم الجديدة.
+        agreed: لقد وافقت على شروط المساهم الجديدة.
         not yet agreed: لم توافق بعد على شروط المساهم الجديدة.
-        review link text: يرجى اتباع هذا الرابط في الوقت الذي يناسبك لمراجعة وقبول
+        review link text: يُرجَى اتباع هذا الرابط في الوقت الذي يناسبك لمراجعة وقبول
           شروط المساهمة الجديدة.
-        agreed_with_pd: وقد أعلنتَ أيضًا أنك تعتبر تعديلاتك ملكية عامة.
+        agreed_with_pd: وقد أعلنت أيضًا أنك تعتبر تعديلاتك ملكية عامة.
         link: https://www.osmfoundation.org/wiki/License/Contributor_Terms
         link text: ما هذا؟
       profile description: 'وصف الملف الشخصي:'
-      preferred languages: 'اÙ\84Ù\84غات Ø§Ù\84Ù\85Ù\81ضÙ\91Ù\84Ø©:'
+      preferred languages: 'اللغات المفضلة:'
       preferred editor: 'المحرر المفضل:'
       image: "\uFEFFالصورة:"
       gravatar:
@@ -2210,12 +2203,12 @@ ar:
       no home location: لم تدخل موقع منزلك.
       latitude: 'خط العرض:'
       longitude: 'خط الطول:'
-      update home location on click: Ø­Ø¯Ù\91ث موقع المنزل عندما أنقر على الخريطة؟
+      update home location on click: ØªØ­Ø¯Ù\8aث موقع المنزل عندما أنقر على الخريطة؟
       save changes button: احفظ التغييرات
       make edits public button: اجعل جميع تعديلاتي عامة
       return to profile: العودة إلى الملف الشخصي
-      flash update success confirm needed: تم تحديث معلومات المستخدم بنجاح. تحقق من
-        بريدك الإلكتروني لمذكرة تأكيد العنوان الإلكتروني الجديد.
+      flash update success confirm needed: تم تحديث معلومات المستخدم بنجاح، تحقق من
+        بريدك الإلكتروني لملاحظة تأكيد العنوان الإلكتروني الجديد.
       flash update success: تم تحديث معلومات المستخدم بنجاح.
     confirm:
       heading: تحقق من بريدك الإلكتروني
@@ -2223,54 +2216,54 @@ ar:
       introduction_2: أكد حسابك عن طريق النقر على الرابط في البريد الإلكتروني وستكون
         قادرا على البدء في رسم الخرائط.
       press confirm button: اضغط على زر التأكيد أدناه لتنشيط حسابك.
-      button: Ø£Ù\83Ù\91د
+      button: ØªØ£Ù\83Ù\8aد
       success: تم تأكيد حسابك، شكرًا للاشتراك!
       already active: هذا الحساب سبق أن تم تأكيده.
       unknown token: رمز التأكيد انتهت صلاحيته أو غير موجود.
-      reconfirm_html: إذا كنت في حاجة لإعادة إرسال تأكيد البريد الإلكتروني، email
-        <a href="%{reconfirm}">انقر هنا</a>.
+      reconfirm_html: إذا كنت في حاجة لإعادة إرسال تأكيد البريد الإلكتروني، <a href="%{reconfirm}">انقر
+        هنا</a>.
     confirm_resend:
       success: لقد أرسلنا رسالة تأكيد جديدة إلى %{email} وبمجرد تأكيد حسابك ستتمكن
-        من رسم الخرائط. <br /> <br /> إذا كنت تستخدم نظامًا مضادًا للبريد العشوائي
-        يرسل طلبات تأكيد ، فيرجى تأكد من أنك القائمة البيضاء %{sender} لأننا غير قادرين
-        على الرد على أي طلبات تأكيد.
+        من رسم الخرائط.<br /><br />إذا كنت تستخدم نظاما مضادا للبريد العشوائي يرسل
+        طلبات تأكيد، فيُرجَى التأكد من أنك وضعت في القائمة البيضاء %{sender} لأننا
+        ØºÙ\8aر Ù\82ادرÙ\8aÙ\86 Ø¹Ù\84Ù\89 Ø§Ù\84رد Ø¹Ù\84Ù\89 Ø£Ù\8a Ø·Ù\84بات ØªØ£Ù\83Ù\8aد.
       failure: المستخدم %{name} غير موجود.
     confirm_email:
-      heading: أكّد تغيير عنوان البريد الإلكتروني
+      heading: أكد تغيير عنوان البريد الإلكتروني
       press confirm button: اضغط على زر تأكيد أدناه لتأكيد عنوان بريدك الإلكتروني
         الجديد.
-      button: Ø£Ù\83Ù\91د
-      success: تم تأكيد عنوان بريدك الإلكتروني، شكرًا للاشتراك!
-      failure: عنوان بريد إلكتروني تم تفعيله مسبقًا بهذا النموذج.
+      button: ØªØ£Ù\83Ù\8aد
+      success: تم تأكيد عنوان بريدك الإلكتروني!
+      failure: عنوان بريد إلكتروني تم تفعيله مسبقًا بهذا الرمز.
       unknown_token: رمز التأكيد انتهت صلاحيته أو غير موجود.
     set_home:
-      flash success: موقع المنزل حُفظ بنجاح
+      flash success: موقع المنزل حُفِظ بنجاح
     go_public:
       flash success: جميع تعديلاتك الآن عامة، ومسموح لك بالتعديل الآن.
     make_friend:
       heading: إضافة %{user} كصديق؟
       button: أضف كصديق
       success: '%{name} الآن صديقك.'
-      failed: عفوًا، تعذر إضافة %{name} كصديق.
-      already_a_friend: حاليًا أنت و %{name} أصدقاء.
+      failed: عفوًا، تعذرت إضافة %{name} كصديق.
+      already_a_friend: حاليًا أنت و%{name} أصدقاء.
     remove_friend:
-      heading: ØºÙ\8aر ØµØ¯Ù\8aÙ\82 %{user}؟
-      button: Ø§لغاء الصداقة
-      success: تم إزالة %{name} من قائمة أصدقائك.
-      not_a_friend: '%{name} ليس من أحد أصدقائك.'
+      heading: Ø¥Ù\84غاء ØµØ¯Ø§Ù\82Ø© %{user}؟
+      button: Ø¥لغاء الصداقة
+      success: تمت إزالة %{name} من قائمة أصدقائك.
+      not_a_friend: '%{name} ليس أحد أصدقائك.'
     filter:
-      not_an_administrator: عليك أن تكون إداري لتنفيذ هذا الإجراء.
+      not_an_administrator: عليك أن تكون إداريا لتنفيذ هذا الإجراء.
     index:
       title: المستخدمون
       heading: المستخدمون
       showing:
-        one: صفحة%{page} (%{first_item} %{items})
-        other: صفحة %{page} (%{first_item}-%{last_item} %{items})
+        one: صفحة %{page} (%{first_item} من %{items})
+        other: صفحة %{page} (%{first_item}-%{last_item} من %{items})
       summary: '%{name} تم إنشاؤها من %{ip_address} في %{date}'
-      summary_no_ip: '%{name} تم إنشاؤها في %{date}'
+      summary_no_ip: '%{name} تم إنشاؤه في %{date}'
       confirm: تأكيد المستخدمين المحددين
       hide: إخفاء المستخدمين المحددين
-      empty: لا سجلات مطابقة تم العثور عليها!
+      empty: لم يتم العثور على مستخدمين متطابقين
     suspended:
       title: حساب معلق
       heading: حساب معلق
@@ -2286,12 +2279,13 @@ ar:
       unknown_signature_algorithm: خوارزمية توقيع غير معروفة
       invalid_scope: نطاق غير صالح
     auth_association:
-      heading: لم يرتبط اسم المستخدم الخاص بك بحساب خريطة الشارع المفتوحة حتى الآن.
-      option_1: إذا كنت جديدا في خريطة الشارع المفتوح، الرجاء إنشاء حساب جديد باستخدام
-        النموذج أدناه.
-      option_2: إذا كان لديك بالفعل حساب، يمكنك الدخول إلى حسابك باستخدام اسم المستخدم
-        وكلمة المرور الخاصة بك ومن ثم ربط الحساب باسم المستخدم الخاص بك في إعدادات
-        المستخدم.
+      heading: لم يرتبط معرفك بحساب خريطة الشارع المفتوحة حتى الآن.
+      option_1: |-
+        إذا كنت جديدا في خريطة الشارع المفتوح، الرجاء إنشاء حساب جديد
+        باستخدام النموذج أدناه.
+      option_2: "إذا كان لديك حساب بالفعل، فيمكنك تسجيل الدخول إلى حسابك \nباستخدام
+        اسم المستخدم وكلمة المرور الخاصة بك، ثم ربط الحساب \nبمعرفك في إعدادات المستخدم
+        الخاصة بك."
   user_role:
     filter:
       not_an_administrator: يحق فقط للإداريين القيام بتغيير دور المستخدم، وأنت لست
index 4bc8748a0fa8c6252742b9ef289dd321cbebac96..b9b90f23aaadaf6e5db94bd422b6bb36f5c50e61 100644 (file)
@@ -1,4 +1,4 @@
-# Messages for Belarusian (Taraškievica orthography) (беларуская (тарашкевіца)‎)
+# Messages for be-tarask (be-tarask)
 # Exported from translatewiki.net
 # Export driver: phpyaml
 # Author: EugeneZelenko
index bc2637a9e5fe18c99b14f04014aad3648ea81fb0..f35ece33a198b596e3443131575e2bbcf4bba5ed 100644 (file)
@@ -2069,6 +2069,7 @@ cs:
         i budoucí příspěvky.
       consider_pd: Navíc k výše uvedené dohodě považuji své příspěvky za volné dílo.
       consider_pd_why: co to znamená?
+      consider_pd_why_url: https://www.osmfoundation.org/wiki/License/Why_would_I_want_my_contributions_to_be_public_domain
       guidance: 'Informace, které pomohou tyto podmínky pochopit: <a href="%{summary}">lidsky
         čitelné shrnutí</a> a nějaké <a href="%{translations}">neoficiální překlady</a>'
       agree: Souhlasím
index ade8ddcbb396c2b7f584b3d54d29966242b9ccf0..8f662f344737bf404ef3930c0d57c79a902a987c 100644 (file)
@@ -963,6 +963,8 @@ da:
       title: Problemer
       select_status: Vælg status
       select_type: Vælg type
+      select_last_updated_by: Vælg sidst opdateret af
+      reported_user: Rapporteret bruger
       not_updated: Ikke opdateret
       search: Søg
       user_not_found: Brugeren findes ikke
@@ -980,6 +982,7 @@ da:
       reopen: Genåbn
       read_reports: Læs rapporter
       new_reports: Nye rapporter
+      comments_on_this_issue: Kommentarer på denne sag
     comments:
       created_at: Den %{datetime}
     reports:
@@ -1697,8 +1700,10 @@ da:
       tags_help: kommasepareret
       visibility: 'Synlighed:'
       visibility_help: hvad betyder det her?
+      visibility_help_url: https://wiki.openstreetmap.org/wiki/Visibility_of_GPS_traces
       upload_button: Upload
       help: Hjælp
+      help_url: https://wiki.openstreetmap.org/wiki/Upload
     create:
       upload_trace: Upload GPS-spor
       trace_uploaded: Din GPX-fil er uploadet og afventer lagring i databasen. Det
@@ -2013,6 +2018,7 @@ da:
       terms declined: Vi er kede af at du har besluttet at du ikke kan acceptere de
         nye vilkår for bidragsydere. For yderligere oplysninger, se venligst <a href="%{url}">denne
         wikiside</a>.
+      terms declined url: https://wiki.openstreetmap.org/wiki/Contributor_Terms_Declined
     terms:
       title: Vilkår for bidragsydere
       heading: Vilkår for bidragsydere
index fd1e7732532c0be755ea549f570dfa55300aadaf..2d29a4cb43a32466349c47305dd4262567e9f394 100644 (file)
@@ -752,7 +752,7 @@ diq:
       output: Vıcyaen
       export_button: Teberdayış
     sidebar:
-      search_results: Neticeyê geyrayışi
+      search_results: Peyniya cıgeyrayışi
       close: Racnê
     search:
       search: Cı geyre
index f6d396f761ffc6d3a490bf1c399413a61bdef261..7b13a894bc860b3e09cddf1deee13f26e34b8a5a 100644 (file)
@@ -1798,6 +1798,7 @@ en:
         other: "GPX file with %{count} points from %{user}"
       description_without_count: "GPX file from %{user}"
   application:
+    permission_denied: You do not have permission to access that action
     require_cookies:
       cookies_needed: "You appear to have cookies disabled - please enable cookies in your browser before continuing."
     require_admin:
index 18266d4ef44a7a57a7f431e3b33ccd8f45194369..9bc8589bb9eeedfe17d891a346f59c94489001e1 100644 (file)
@@ -1369,6 +1369,10 @@ eo:
           <strong>Aŭstrujo</strong>: enhavas datumojn el <a href="https://data.wien.gv.at/">Stadt Wien</a> (laŭ <a href="https://creativecommons.org/licenses/by/3.0/at/deed.eo">CC BY</a>),
           <a href="https://www.vorarlberg.at/vorarlberg/bauen_wohnen/bauen/vermessung_geoinformation/weitereinformationen/services/wmsdienste.htm">Land Vorarlberg</a> kaj
           Land Tirol (laŭ <a href="https://www.tirol.gv.at/applikationen/e-government/data/nutzungsbedingungen/">CC BY AT kun postaj ŝanĝoj</a>).
+        contributors_au_html: '<strong>Aŭstralio</strong>: enhavas datumojn el <a
+          href="https://www.psma.com.au/psma-data-copyright-and-disclaimer">PSMA Australia
+          Limited</a> kunhavigataj de Komunejo de Aŭstralio laŭ la permesilo <a href="https://creativecommons.org/licenses/by/4.0/deed.eo">CC
+          BY 4.0</a>.'
         contributors_ca_html: |-
           <strong>Kanado</strong>: enhavas datumojn el
           GeoBase&reg;, GeoGratis (&copy; Department of Natural
index 5645cb5a956ec66dbae58452ac07ef8fd1b98ef1..047d22ef5a624f5463cacf55f71853d8a7bb131f 100644 (file)
@@ -428,7 +428,7 @@ fa:
           ferry_terminal: پایانه کشتی
           fire_station: آتش‌نشانی
           food_court: پذيرايي
-          fountain: چشمه
+          fountain: فواره
           fuel: پمپ بنزین
           gambling: قمار
           grave_yard: محوطهٔ گورستان
@@ -1048,7 +1048,7 @@ fa:
       befriend_them: همچنین میتوانید در %{befriendurl} او را بعنوان دوست اضافه کنید.
     gpx_notification:
       greeting: سلام ،
-      your_gpx_file: Ù¾Ø±Ù\88Ù\86دÙ\87 Û\8c GPX شما اینگونه است
+      your_gpx_file: Ù\81اÛ\8cÙ\84 GPX شما اینگونه است
       with_description: با توضیحات
       and_the_tags: 'و برچسب های زیر:'
       and_no_tags: و بدون برچسب.
@@ -1636,8 +1636,8 @@ fa:
       identifiable: قابل شناسایی (نمایش در لیست ردها، قابل شناسایی، نقاط مرتب بر اساس
         زمان)
     new:
-      upload_trace: بارگذاری رد GPS
-      upload_gpx: 'بارگذارÛ\8c Ù¾Ø±Ù\88Ù\86دÙ\87Ù\94 GPX:'
+      upload_trace: بارگذاری رد جی‌پی‌اس
+      upload_gpx: 'بارگذارÛ\8c Ù\81اÛ\8cÙ\84 GPX:'
       description: 'توضیحات:'
       tags: 'برچسب‌ها:'
       tags_help: جداشده با کاما (,)
@@ -1646,10 +1646,10 @@ fa:
       upload_button: بارگذاری
       help: کمک
     create:
-      upload_trace: بارگذاری رد GPS
-      trace_uploaded: Ù¾Ø±Ù\88Ù\86دÙ\87Ù\94 GPX Ø´Ù\85ا Ø¨Ø§Ø±Ú¯Ø°Ø§Ø±Û\8c Ø´Ø¯Ù\87 Ù\88 Ø¯Ø± Ø§Ù\86تظار Ø¯Ø±Ø¬ Ø¯Ø± Ù¾Ø§Û\8cگاÙ\87â\80\8cدادÙ\87
-        است. این کار معمولاً کمتر از نیم ساعت طول می‌کشد. هنگامی که انجام شد ایمیلی
-        Ø¨Ø±Ø§Û\8c Ø´Ù\85ا Ù\81رستادÙ\87 Ù\85Û\8câ\80\8cØ´Ù\88د.
+      upload_trace: بارگذاری رد جی‌پی‌اس
+      trace_uploaded: Ù\81اÛ\8cÙ\84 GPX Ø´Ù\85ا Ø¨Ø§Ø±Ú¯Ø°Ø§Ø±Û\8c Ø´Ø¯Ù\87 Ù\88 Ø¯Ø± Ø§Ù\86تظار Ø¯Ø±Ø¬ Ø¯Ø± Ù¾Ø§Û\8cگاÙ\87â\80\8cدادÙ\87 Ø§Ø³Øª.
+        این کار معمولاً کمتر از نیم ساعت طول می‌کشد. هنگامی که انجام شد ایمیلی برای
+        شما فرستاده می‌شود.
       traces_waiting:
         one: شما %{count} رد منتظر بارگذاری دارید. لطفاً قبل از بارگذاری موارد بیشتر
           منتظر بمانید تا اینها بارگذاری بشوند که صف برای سایر کاربران بسته نشود.
@@ -1658,7 +1658,7 @@ fa:
     edit:
       title: ویرایش رد %{name}
       heading: ویرایش رد %{name}
-      filename: 'Ù\86اÙ\85 Ù¾Ø±Ù\88Ù\86دÙ\87:'
+      filename: 'Ù\86اÙ\85 Ù\81اÛ\8cÙ\84:'
       download: دریافت
       uploaded_at: 'تاریخ بارگذاری:'
       points: 'نقاط:'
@@ -1680,7 +1680,7 @@ fa:
       title: دیدن رد %{name}
       heading: دیدن رد %{name}
       pending: در انتظار
-      filename: 'Ù\86اÙ\85 Ù¾Ø±Ù\88Ù\86دÙ\87:'
+      filename: 'Ù\86اÙ\85 Ù\81اÛ\8cÙ\84:'
       download: دریافت
       uploaded: 'تاریخ بارگذاری:'
       points: 'نقاط:'
@@ -1736,15 +1736,14 @@ fa:
       message: سامانهٔ بارگذاری جی‌پی‌اکس در حال حاضر در دسترس نیست
     offline:
       heading: ذخیره سازی آفلاین GPX
-      message: ذخیره‌سازی پروندهٔ جی‌پی‌اکس و سامانهٔ بارگذاری در حال حاضر در دسترس
-        نیست.
+      message: ذخیره‌گاه فایل جی‌پی‌اکس و سامانهٔ بارگذاری هم‌اکنون در دسترس نیستند.
     georss:
-      title: ردهای جی‌پی‌اس OpenStreetMap
+      title: ‫ردهای جی‌پی‌اس OpenStreetMap‬
     description:
       description_with_count:
-        one: پرونده GPX با %{count} نقطه از %{user}
-        other: ' پرونده GPX با %{count} نقطه از %{user}'
-      description_without_count: Ù¾Ø±Ù\88Ù\86دÙ\87 GPX از %{user}
+        one: ‫فایل GPX با %{count} نقطه از %{user}‬
+        other: ' ‫فایل GPX با %{count} نقطه از %{user}‬'
+      description_without_count: Ù\81اÛ\8cÙ\84 GPX از %{user}
   application:
     require_cookies:
       cookies_needed: بنظر می‌رسد که کوکی‌ها را غیرفعال کرده‌اید - لطفاً قبل از ادامه
@@ -1772,7 +1771,7 @@ fa:
       allow_write_diary: ساخت روزنوشت‌ها، نظردادن و افزودن دوست.
       allow_write_api: ویرایش نقشه.
       allow_read_gpx: خواندن ردهای GPS شخصی شما.
-      allow_write_gpx: بارگذاری ردهای GPS
+      allow_write_gpx: بارگذاری ردهای GPS.
       allow_write_notes: اصلاح یادداشت‌ها.
       grant_access: دسترسی می‌دهم
     authorize_success:
@@ -2418,9 +2417,11 @@ fa:
         unhide_comment: نمایش
     notes:
       new:
-        intro: چیزی مشکل دارد؟ به نقشه‌کش‌های دیگر اصلاع دهید تا آن را اصلاح کنند.
-          علامت موشواره را بر روی محلی که مشکل دارد قرار دهید و مشکل را شرح دهید (لطفاً
-          اطلاعات شخصی در بخش ننویسید یا اطلاعاتی از حق تکثیر نقشه یا فهرست دایرکتوری‌ها)
+        intro: مشکلی بر روی نقشه پیدا کرده‌اید یا چیزی از قلم افتاده؟ به نقشه‌کش‌های
+          دیگر اطلاع دهید تا آن را اصلاح کنند. نشانه را بر روی محلی که مشکل دارد قرار
+          دهید و با نوشتن یادداشت، مشکل را به‌طور کامل شرح دهید.
+        advice: همهٔ افراد این یادداشت شما را می‌بینند. بنابراین اطلاعات خصوصی یا
+          اطلاعات برداشت‌شده از منابع دارای حق تکثیر را اینجا ننویسید.
         add: افزودن یادداشت
       show:
         anonymous_warning: این یادداشت شامل نظرات کاربران ناشناس است که باید به‌طور
@@ -2428,7 +2429,7 @@ fa:
         hide: نهفتن
         resolve: حل شد
         reactivate: فعال سازی مجدد
-        comment_and_resolve: نظر و راه حل
+        comment_and_resolve: نظر + حل شد
         comment: نظر
     edit_help: نقشه را جابجا کنید و روی مکانی که می‌خواهید ویرایش کنید بزرگنمایی کنید،
       سپس اینجا کلیک کنید.
index ec9a904cae7e088d97d74ce0e1dd07ab72ee2a50..26cc5443ce60acc518ad4d6cbbfcdb1440d13fa0 100644 (file)
@@ -23,8 +23,8 @@ gl:
   activerecord:
     models:
       acl: Listaxe do control de acceso
-      changeset: Conxunto de cambios
-      changeset_tag: Etiqueta do conxunto de cambios
+      changeset: Conxunto de mudanzas
+      changeset_tag: Etiqueta do conxunto de mudanzas
       country: País
       diary_comment: Comentario do diario
       diary_entry: Entrada do diario
@@ -115,7 +115,7 @@ gl:
     edited_by_html: Editado <abbr title='%{title}'>hai %{time}</abbr> por %{user}
     closed_by_html: Pechado <abbr title='%{title}'>hai %{time}</abbr> por %{user}
     version: Versión
-    in_changeset: Conxunto de cambios
+    in_changeset: Conxunto de mudanzas
     anonymous: anónimo
     no_comment: (sen comentarios)
     part_of: Parte de
@@ -124,7 +124,7 @@ gl:
     view_details: Ve-los detalles
     location: 'Localización:'
     changeset:
-      title: 'Conxunto de cambios: %{id}'
+      title: 'Conxunto de mudanzas: %{id}'
       belongs_to: Autor
       node: Nós (%{count})
       node_paginated: Nós (%{x}-%{y} de %{count})
@@ -136,15 +136,15 @@ gl:
       hidden_commented_by: Comentario agochado de %{user} <abbr title='%{exact_time}'>
         hai %{when}</abbr>
       commented_by: Comentario de %{user} <abbr title='%{exact_time}'> hai %{when}</abbr>
-      changesetxml: Conxunto de cambios do XML
+      changesetxml: Conxunto de mudanzas do XML
       osmchangexml: osmChange XML
       feed:
-        title: Conxunto de cambios %{id}
-        title_comment: Conxunto de cambios %{id} - %{comment}
+        title: Conxunto de mudanzas %{id}
+        title_comment: Conxunto de mudanzas %{id} - %{comment}
       join_discussion: Inicia-la sesión pra unirse á parola
       discussion: Parola
-      still_open: O conxunto de cambios segue aberto - Abrirase a parola cando o conxunto
-        de cambios estea pechado.
+      still_open: O conxunto de mudanzas segue aberto - Abrirase a parola cando o
+        conxunto de mudanzas estea pechado.
     node:
       title: 'Nó: %{name}'
       history_title: 'Historial do nó: %{name}'
@@ -175,7 +175,7 @@ gl:
         node: nó
         way: camiño
         relation: relación
-        changeset: conxunto de cambios
+        changeset: conxunto de mudanzas
         note: nota
     timeout:
       sorry: Tardouse demasiado en obter os datos para o %{type} co id %{id}.
@@ -183,7 +183,7 @@ gl:
         node: nó
         way: camiño
         relation: relación
-        changeset: conxunto de cambios
+        changeset: conxunto de mudanzas
         note: nota
     redacted:
       redaction: Redacción %{id}
@@ -229,8 +229,8 @@ gl:
       report: Informar desta nota
     query:
       title: Consulta-las características
-      introduction: Prema no mapa para atopar características preto daquí.
-      nearby: Características preto daquí
+      introduction: Prema no mapa para atopar características preto daquí.
+      nearby: Características preto daquí
       enclosing: Características envolventes
   changeset:
     changeset_paging_nav:
@@ -240,7 +240,7 @@ gl:
     changeset:
       anonymous: Anónimo
       no_edits: (sen edicións)
-      view_changeset_details: Ve-los detalles do conxunto de cambios
+      view_changeset_details: Ve-los detalles do conxunto de mudanzas
     changesets:
       id: ID
       saved_at: Gardado o
@@ -248,24 +248,24 @@ gl:
       comment: Comentario
       area: Zona
     index:
-      title: Conxuntos de cambios
-      title_user: Conxuntos de cambios por %{user}
-      title_friend: Conxuntos de cambios das amizades
-      title_nearby: Conxuntos de cambios dos usuarios de lugares preto de ti
-      empty: Non se atoparon conxuntos de cambios.
-      empty_area: Non hai conxuntos de cambios nesta zona.
-      empty_user: Non hai conxuntos de cambios deste usuario.
-      no_more: Non se atoparon máis conxuntos de cambios.
-      no_more_area: Non hai máis conxuntos de cambios nesta zona.
-      no_more_user: Non hai máis conxuntos de cambios deste usuario.
+      title: Conxuntos de mudanzas
+      title_user: Conxuntos de mudanzas por %{user}
+      title_friend: Conxuntos de mudanzas das amizades
+      title_nearby: Conxuntos de mudanzas dos usuarios de lugares preto de ti
+      empty: Non se atoparon conxuntos de mudanzas.
+      empty_area: Non hai conxuntos de mudanzas nesta zona.
+      empty_user: Non hai conxuntos de mudanzas deste usuario.
+      no_more: Non se atoparon máis conxuntos de mudanzas.
+      no_more_area: Non hai máis conxuntos de mudanzas nesta zona.
+      no_more_user: Non hai máis conxuntos de mudanzas deste usuario.
       load_more: Cargar máis
     timeout:
-      sorry: Desculpe que levase moito tempo obter a listaxe do conxunto de cambios
+      sorry: Desculpe que levase moito tempo obte-la listaxe do conxunto de mudanzas
         que solicitou.
     rss:
       title_all: Parola da edición no OpenStreetMap
       title_particular: 'Parola da edición #%{changeset_id} no OpenStreetMap'
-      comment: 'Novo comentario sobre os cambios #%{changeset_id} de %{author}'
+      comment: 'Novo comentario sobre as mudanzas #%{changeset_id} de %{author}'
       commented_at_html: Actualizado hai %{when}
       commented_at_by_html: Actualizado hai %{when} por %{user}
       full: Parola completa
@@ -794,7 +794,7 @@ gl:
           stop: Parada de ferrocarril
           subway: Metro
           subway_entrance: Boca de metro
-          switch: Puntos de cambio de vía
+          switch: Puntos de mudanza de vía
           tram: Vía de tranvías
           tram_stop: Parada de tranvías
         shop:
@@ -1151,13 +1151,13 @@ gl:
       subject: '[OpenStreetMap] Confirme o seu enderezo de correo electrónico'
     email_confirm_plain:
       greeting: 'Ola:'
-      hopefully_you: Alguén (probablemente vostede) quere cambiar o seu enderezo de
+      hopefully_you: Alguén (probábelmente vostede) quere muda-lo seu enderezo do
         correo electrónico en %{server_url} a %{new_address}.
       click_the_link: Se este é vostede, prema na seguinte ligazón para confirma-la
         modificación.
     email_confirm_html:
       greeting: 'Ola:'
-      hopefully_you: Alguén (probablemente vostede) quere cambiar o seu enderezo de
+      hopefully_you: Alguén (probábelmente vostede) quere muda-lo seu enderezo do
         correo electrónico en %{server_url} a %{new_address}.
       click_the_link: Se este é vostede, prema na seguinte ligazón para confirma-la
         modificación.
@@ -1206,17 +1206,17 @@ gl:
       greeting: Ola,
       commented:
         subject_own: O %{commenter} de [OpenStreetMap] fixo un comentario nun dos
-          seus conxuntos de cambios
-        subject_other: '[OpenStreetMap] %{commenter} comentou nun conxunto de cambios
+          seus conxuntos de mudanzas
+        subject_other: '[OpenStreetMap] %{commenter} comentou nun conxunto de mudanzas
           no que estás atinxido'
         your_changeset: '%{commenter} deixou un comentario nun dos seus conxuntos
-          de cambios xerado o %{time}'
-        commented_changeset: '%{commenter} deixou un comentario nun conxunto de cambios
-          do mapa que está seguindo, xerado por %{changeset_author} o %{time}'
+          de mudanzas xerado o %{time}'
+        commented_changeset: '%{commenter} deixou un comentario nun conxunto de mudanzas
+          do mapa que está a seguer, xerado por %{changeset_author} o %{time}'
         partial_changeset_with_comment: co comentario '%{changeset_comment}'
         partial_changeset_without_comment: sen comentarios
-      details: Pódense atopar máis detalles acerca do conxunto de cambios en %{url}.
-      unsubscribe: Para darse de baixa das actualizacións deste conxunto de cambios,
+      details: Pódense atopar máis detalles acerca do conxunto de mudanzas en %{url}.
+      unsubscribe: Para darse de baixa das actualizacións deste conxunto de mudanzas,
         olle %{url} e prema en "darse de baixa".
   messages:
     inbox:
@@ -1489,12 +1489,12 @@ gl:
         Flash de OpenStreetMap. Pode <a href="https://get.adobe.com/flashplayer/">descargar
         Flash do sitio Adobe.com</a>. <a href="https://wiki.openstreetmap.org/wiki/Editing">Tamén
         están dispoñíbeis outras opcións</a> para editar OpenStreetMap.
-      potlatch_unsaved_changes: Ten cambios sen gardar. (Para gardalos no Potlatch
-        ten que desmarcar o camiño actual ou o punto se está a editar no modo en vivo
+      potlatch_unsaved_changes: Ten mudanzas sen gardar. (Para gardalas no Potlatch
+        ten que desmarca-la vía actual ou o punto se está a editar no modo ao vivo
         ou premer sobre o botón "Gardar".)
       potlatch2_not_configured: O Potlatch 2 non está configurado; consulte https://wiki.openstreetmap.org/wiki/The_Rails_Port
         para obter máis información
-      potlatch2_unsaved_changes: Ten cambios sen gardar. (Para gardar no Potlatch
+      potlatch2_unsaved_changes: Ten mudanzas sen gardar. (Para gardar no Potlatch
         2, prema en "Gardar".)
       id_not_configured: O iD non está configurado
       no_iframe_support: O seu navegador non soporta os iframes HTML, necesarios para
@@ -1801,7 +1801,7 @@ gl:
       description: 'Descrición:'
       tags: 'Etiquetas:'
       tags_help: separadas por comas
-      save_button: Garda-los cambios
+      save_button: Garda-las mudanzas
       visibility: 'Visibilidade:'
       visibility_help: que significa isto?
       visibility_help_url: https://wiki.openstreetmap.org/wiki/Visibility_of_GPS_traces
@@ -2186,9 +2186,9 @@ gl:
       unhide_user: Descobrir este usuario
       delete_user: Borrar este usuario
       confirm: Confirmar
-      friends_changesets: conxuntos de cambios das amizades
+      friends_changesets: conxuntos de mudanzas das amizades
       friends_diaries: entradas de diario das amizades
-      nearby_changesets: conxuntos de cambios dos usuarios de lugares preto de ti
+      nearby_changesets: conxuntos de mudanzas dos usuarios de lugares preto de ti
       nearby_diaries: entradas de diario dos usuarios de lugares preto de ti
       report: Denunciar este usuario
     popup:
@@ -2254,7 +2254,7 @@ gl:
       longitude: 'Lonxitude:'
       update home location on click: Quere actualiza-lo lugar do enderezo ó premer
         sobre o mapa?
-      save changes button: Garda-los cambios
+      save changes button: Garda-las mudanzas
       make edits public button: Facer públicas todas as miñas edicións
       return to profile: Voltar ó perfil
       flash update success confirm needed: Información de usuario actualizada correctamente.
@@ -2280,11 +2280,11 @@ gl:
         proceso sen problemas.
       failure: Non se atopou o usuario "%{name}".
     confirm_email:
-      heading: Confirma-lo cambio do enderezo de correo electrónico
+      heading: Confirma-la mudanza do enderezo de correo electrónico
       press confirm button: Prema sobre o botón de confirmación que aparece deseguido
         para confirmar o seu novo enderezo de correo electrónico.
       button: Confirmar
-      success: Confirmámoslle o cambio enderezo de enderezo electrónico!
+      success: Confirmámoslle a mudanza do enderezo de correo electrónico!
       failure: Xa se confirmou un enderezo de correo electrónico con este pase.
       unknown_token: Ese código de confirmación caducou ou non existe.
     set_home:
@@ -2725,7 +2725,7 @@ gl:
     create:
       flash: Redacción creada.
     update:
-      flash: Gardáronse os cambios.
+      flash: Gardáronse as mudanzas.
     destroy:
       not_empty: A redacción non está baleira. Elimine todas as versións previas pertencentes
         a esta redacción antes de destruíla.
index 786bf965f41aade38a2f3e58a343598c0ecc5d25..be3e04583480addc1911f7355856a6c8938b0219 100644 (file)
@@ -222,6 +222,7 @@ lv:
       reopened_by_anonymous: Atkal aktivizēja anonīms <abbr title='%{exact_time}'>%{when}
         atpakaļ</abbr>
       hidden_by: Paslēpa %{user} <abbr title='%{exact_time}'>%{when} atpakaļ</abbr>
+      report: Ziņot par šo piezīmi
     query:
       title: Vaicājuma funkcijas
       introduction: Noklikšķiniet uz kartes, lai atrastu tuvumā esošos objektus.
@@ -623,6 +624,7 @@ lv:
           bridge: Tilts
           bunker_silo: Bunkurs
           chimney: Skurstenis
+          flagpole: Karoga masts
           lighthouse: Bāka
           pipeline: Cauruļvads
           tower: Tornis
@@ -801,6 +803,7 @@ lv:
           pet: Zooveikals
           pharmacy: Aptieka
           photo: Fotoveikals
+          seafood: Jūras veltes
           second_hand: Lietoto preču veikals
           shoes: Apavu veikals
           sports: Sporta veikals
@@ -879,6 +882,7 @@ lv:
     index:
       search: Meklēt
       status: Statuss
+      reports: Ziņojumi
       states:
         ignored: Ignorēts
         open: Atvērt
index f14976f12e79533ddf4e6beca5d596a02c6ac9ce..28b3d7f598b9a7710f8a98f9efbaefebdda82b4e 100644 (file)
@@ -10,6 +10,7 @@
 # Author: Greencaps
 # Author: HanV
 # Author: Hansmuller
+# Author: Henke
 # Author: JaapDeKleine
 # Author: Jochempluim
 # Author: Joost schouppe
@@ -24,6 +25,7 @@
 # Author: MrLeopold
 # Author: Optilete
 # Author: Pje335
+# Author: Robin van der Linde
 # Author: Robin van der Vliet
 # Author: Robin0van0der0vliet
 # Author: Romaine
@@ -252,6 +254,7 @@ nl:
       reopened_by_anonymous: <abbr title='%{exact_time}'>%{when} geleden</abbr> opnieuw
         geactiveerd door anoniem
       hidden_by: <abbr title='%{exact_time}'>%{when} ago</abbr> verborgen door %{user}
+      report: Notitie rapporteren
     query:
       title: Nabije objecten opvragen
       introduction: Klik op de kaart om nabije eigenschappen te ontdekken.
@@ -348,6 +351,7 @@ nl:
       comment_from: Reactie van %{link_user} op %{comment_created_at}
       hide_link: Reactie verbergen
       confirm: Bevestigen
+      report: Rapporteer deze opmerking
     location:
       location: 'Locatie:'
       view: Bekijken
@@ -499,6 +503,7 @@ nl:
           protected_area: Beschermd gebied
         bridge:
           aqueduct: Aquaduct
+          boardwalk: Plankenweg
           suspension: Hangbrug
           swing: Draaibrug
           viaduct: Viaduct
@@ -524,11 +529,11 @@ nl:
           water_tank: Watertank voor noodgevallen
           "yes": Noodgeval
         highway:
-          abandoned: Verlaten snelweg
+          abandoned: Verlaten weg
           bridleway: Ruiterpad
           bus_guideway: Vrijliggende busbaan
           bus_stop: Bushalte
-          construction: Snelweg in aanbouw
+          construction: Weg in aanbouw
           corridor: Corridor
           cycleway: Fietspad
           elevator: Lift
@@ -565,7 +570,7 @@ nl:
           track: Veld- of bosweg
           traffic_signals: Verkeerslichten
           trail: Pad
-          trunk: Autosnelweg
+          trunk: Autoweg
           trunk_link: Autoweg
           turning_loop: Keerlus
           unclassified: Ongeclassificeerde weg
@@ -691,6 +696,7 @@ nl:
           wastewater_plant: Afvalwaterzuivering
           watermill: Watermolen
           water_tower: Watertoren
+          water_well: Put
           water_works: Waterwerken
           windmill: Windmolen
           works: Fabriek
@@ -780,7 +786,7 @@ nl:
           square: Plein
           state: Staat
           subdivision: Deelgebied
-          suburb: Buitenwijk
+          suburb: Stadsdeel
           town: Stad
           unincorporated_area: Gemeentevrij gebied
           village: Dorp
@@ -870,9 +876,11 @@ nl:
           organic: Organische winkel
           outdoor: Buitensportwinkel
           paint: Verfwinkel
+          pawnbroker: Pandmakelaar
           pet: Dierenwinkel
           pharmacy: Apotheek
           photo: Fotowinkel
+          seafood: Zeevruchten
           second_hand: Kringloopwinkel
           shoes: Schoenenzaak
           sports: Sportwinkel
@@ -882,6 +890,7 @@ nl:
           tobacco: Tabakswinkel
           toys: Speelgoedwinkel
           travel_agency: Reisbureau
+          tyres: Bandenwinkel
           video: Videotheek
           wine: Wijnwinkel
           "yes": Winkel
@@ -935,7 +944,7 @@ nl:
         level6: Countygrens
         level8: Stadsgrens
         level9: Dorpsgrens
-        level10: Wijkgrens
+        level10: Stadsdeelgrens
     description:
       title:
         osm_nominatim: Locatie van <a href="https://nominatim.openstreetmap.org/">OpenStreetMap
@@ -948,6 +957,74 @@ nl:
     results:
       no_results: Geen resultaten gevonden
       more_results: Meer resultaten
+  issues:
+    index:
+      title: Problemen
+      select_status: Selecteer Status
+      select_type: Selecteer Type
+      select_last_updated_by: Selecteer Laats Bijgewerkt Door
+      reported_user: Gerapporteerde Gebruiker
+      not_updated: Niet Bijgewerkt
+      search: Zoeken
+      search_guidance: 'Zoek Problemen:'
+      user_not_found: Gebruiker bestaat niet
+      status: Status
+      reports: Rapportages
+      last_updated: Laatst Bijgewerkt
+      reported_item: Gerapporteerd Item
+      states:
+        ignored: Genegeerd
+        open: Open
+        resolved: Opgelost
+    update:
+      new_report: Uw rapport is succesvol geregistreerd
+      successful_update: Uw rapport is succesvol bijgewerkt
+      provide_details: Geef a.u.b. de vereiste gegevens in
+    show:
+      title: '%{status} Probleem #%{issue_id}'
+      report_created_at: Voor het eerst vermeld op %{datetime}
+      last_resolved_at: Laatst opgelost op %{datetime}
+      last_updated_at: Laatst bijgewerkt op %{datetime} door %{displayname}
+      resolve: Oplossen
+      ignore: Negeren
+      reopen: Heropenen
+      reports_of_this_issue: Meldingen van deze kwestie
+      read_reports: Lees Meldingen
+      new_reports: Nieuwe Meldingen
+      other_issues_against_this_user: Andere problemen met deze gebruiker
+      no_other_issues: Geen andere problemen tegen deze gebruiker.
+      comments_on_this_issue: Commentaar op deze kwestie
+    resolve:
+      resolved: De status van het probleem is ingesteld op 'Opgelost'
+    ignore:
+      ignored: De status van het probleem is ingesteld op 'Genegeerd'
+    reopen:
+      reopened: De status van het probleem is ingesteld op 'Open'
+    comments:
+      created_at: Op %{datetime}
+      reassign_param: Probleem opnieuw toewijzen?
+    reports:
+      updated_at: Op %{datetime}
+      reported_by_html: Gerapporteerd als %{category} door %{user}
+    helper:
+      reportable_title:
+        diary_comment: '%{entry_title}, commentaar #%{comment_id}'
+        note: 'Nota #%{note_id}'
+  issue_comments:
+    create:
+      comment_created: Je reactie is succesvol gemaakt
+  reports:
+    new:
+      categories:
+        diary_entry:
+          other_label: Anders
+        diary_comment:
+          other_label: Anders
+        user:
+          other_label: Anders
+        note:
+          spam_label: Deze notitie is spam
+          other_label: Anders
   layouts:
     logo:
       alt_text: Logo OpenStreetMap
@@ -973,6 +1050,8 @@ nl:
     intro_text: OpenStreetMap is een kaart van de wereld, gemaakt door mensen zoals
       u en vrij te gebruiken onder een open licentie.
     intro_2_create_account: Maak een gebruiker aan
+    hosting_partners_html: Hosting wordt ondersteund door %{ucl}, %{bytemark}, en
+      andere %{partners}.
     partners_ucl: het UCL VR Centre
     partners_bytemark: Bytemark Hosting
     partners_partners: partners
@@ -2061,6 +2140,7 @@ nl:
       friends_diaries: dagboekberichten van vrienden
       nearby_changesets: wijzigingensets van gebruikers in de buurt
       nearby_diaries: dagboekberichten van gebruikers in de buurt
+      report: Rapporteer deze Gebruiker
     popup:
       your location: Uw locatie
       nearby mapper: Dichtbijzijnde mapper
@@ -2500,6 +2580,14 @@ nl:
         roundabout_with_exit: Neem op de rotonde afslag %{exit} naar %{name}
         unnamed: naamloos
         courtesy: Routebeschrijving met dank aan %{link}
+        exit_counts:
+          first: 1e
+          second: 2e
+          third: 3e
+          fourth: 4e
+          fifth: 5e
+          sixth: 6e
+          seventh: 7e
       time: Tijd
     query:
       node: Node
index bf63c2946509bf7ca143ec39b9c52ebf57c12896..b96c5c69442de24a0e34be573011e40002208397 100644 (file)
@@ -2091,6 +2091,7 @@ pt-PT:
       terms accepted: Obrigado por aceitar os novos termos de colaborador!
       terms declined: Lamentamos não ter aceitado os novos Termos de Colaborador.
         Para obter mais informações consulte <a href="%{url}">esta página wiki</a>.
+      terms declined url: https://wiki.openstreetmap.org/wiki/Contributor_Terms_Declined
     terms:
       title: Termos de colaborador
       heading: Termos de colaborador
@@ -2100,9 +2101,11 @@ pt-PT:
       consider_pd: para além do acordo exposto acima, considero que as minhas contribuições
         se encontram em Domínio Público.
       consider_pd_why: O que é isto?
+      consider_pd_why_url: https://www.osmfoundation.org/wiki/License/Why_would_I_want_my_contributions_to_be_public_domain
       guidance: 'Informação para ajudar a compreender os termos: um <a href="%{summary}">resumo
         inteligível</a> e algumas <a href="%{translations}">traduções informais</a>'
       agree: Aceitar
+      declined: https://wiki.openstreetmap.org/wiki/Contributor_Terms_Declined
       decline: Rejeitar
       you need to accept or decline: Por favor leia e depois aceite ou recuse os novos
         Termos de Colaborador para continuar.
@@ -2225,6 +2228,7 @@ pt-PT:
           os Termos de Colaborador.
         agreed_with_pd: Também declarou que as suas edições são disponibilizadas em
           Domínio Público.
+        link: https://www.osmfoundation.org/wiki/License/Contributor_Terms
         link text: o que é isto?
       profile description: 'Descrição do perfil:'
       preferred languages: 'Línguas preferidas:'
@@ -2232,6 +2236,7 @@ pt-PT:
       image: 'Imagem:'
       gravatar:
         gravatar: Usar imagem do site Gravatar
+        link: https://wiki.openstreetmap.org/wiki/Gravatar
         link text: o que é isto?
         disabled: O Gravatar foi desativado.
         enabled: A visualização do seu avatar de Gravatar foi ativada.
index b670383ad8212495d4c9b3ede9b859a858346de5..cb80616a461db291c07e9757b829b7268a7ea82f 100644 (file)
@@ -1272,7 +1272,7 @@ sr:
         attribution_example:
           alt: Пример како да наведете Опенстритмап на некој страници
           title: Пример за навођење
-        more_title_html: Ð¡Ð°Ð·Ð½Ð°Ñ\98 Ð²Ð¸Ñ\88е
+        more_title_html: Ð\92иÑ\88е Ð¾
         more_1_html: |-
           Више о употреби података и како да нас наводите можете наћи на <a
           href="http://osmfoundation.org/Licence">страници лиценце OSMF</a> и у <a
index 250f2376f7b2c99e268e5b817b08e1f250582937..7f8e7d7cd5ee9a6d5f55b215a25cd2f26e4e18e2 100644 (file)
@@ -192,7 +192,7 @@ th:
         tag: หน้าคำอธิบายวิกิาสำหรับป้ายระบุ %{key}=%{value}
       wikidata_link: รายการ %{page} ที่วิกิสนเทศ
       wikipedia_link: บทความ %{page} ที่วิกิพีเดีย
-      telephone_link: à¹\82à¸\97รศัà¸\9eà¸\97à¹\8cà¹\84à¸\9bà¹\80ลà¸\82หมาย %{phone_number}
+      telephone_link: à¹\82à¸\97รศัà¸\9eà¸\97à¹\8cà¹\84à¸\9bà¸\97ีà¹\88หมายà¹\80ลà¸\82 %{phone_number}
     note:
       title: 'หมายเหตุ: %{id}'
       new_note: หมายเหตุใหม่
@@ -448,7 +448,7 @@ th:
           social_facility: สโมสรพบปะ
           studio: สถานที่บันทึกภาพและเสียง
           swimming_pool: สระว่ายน้ำ
-          taxi: à¸£à¸\96แท็กซี่
+          taxi: à¸\88ุà¸\94à¸\88อà¸\94แท็กซี่
           telephone: โทรศัพท์สาธารณะ
           theatre: โรงละคร
           toilets: ห้องน้ำสาธารณะ
@@ -809,7 +809,7 @@ th:
           deli: ร้านขายอาหารพิเศษ
           department_store: ห้างสรรพสินค้า
           discount: ร้านสินค้าลดราคา
-          doityourself: à¸\97ำà¸\94à¹\89วยà¸\95ัวà¸\97à¹\88าà¸\99à¹\80อà¸\87
+          doityourself: à¸£à¹\89าà¸\99อุà¸\9bà¸\81รà¸\93à¹\8cà¸\8aà¹\88าà¸\87à¸\9bระà¸\88ำà¸\9aà¹\89าà¸\99
           dry_cleaning: ร้านซักแห้ง
           electronics: ร้านเครื่องไฟฟ้า
           estate_agent: บริษัทอสังหาริมทรัพย์
@@ -946,6 +946,13 @@ th:
       created_at: เมื่อ %{datetime}
   reports:
     new:
+      title_html: แจ้งปัญหาเกี่ยวกับ %{link}
+      select: 'เลือกประเภทของปัญหาที่ประสงค์จะแจ้ง:'
+      disclaimer:
+        intro: 'ก่อนที่จะแจ้งปัญหาไปยังผู้ดูแล ขอให้ดูจนแน่ใจก่อนว่า:'
+        not_just_mistake: ปัญหานี้ไม่ได้เกิดจากเพียงความพลั้งเผลอ
+        unable_to_fix: คุณและผู้ใช้คนอื่นไม่สามารถเข้าไปแก้ปัญหานี้ด้วยตัวเอง
+        resolve_with_user: คุณได้พยายามพูดคุยแก้ไขปัญหากับผู้ใช้คนดังกล่าวแล้ว
       categories:
         diary_entry:
           threat_label: บันทึกนี้มีใจความข่มขู่คุกคาม
@@ -962,6 +969,7 @@ th:
           abusive_label: หมายเหตุนี้ใช้ถ้อยคำหยาบคายหรือส่งเสริมความรุนแรง
           other_label: อื่นๆ
     create:
+      successful_report: ทำการแจ้งปัญหาเสร็จสิ้นเรียบร้อย
       provide_details: กรุณาระบุรายละเอียด
   layouts:
     logo:
@@ -1297,7 +1305,10 @@ th:
         infringement_2_html: |-
           หากท่านเชื่อว่าข้อมูลละเมิดลิขสิทธิ์ปรากฏในเว็บไซต์นี้หรือในฐานข้อมูล OpenStreetMap โปรดดู <a href="https://www.osmfoundation.org/wiki/License/Takedown_procedure">ขั้นตอนการลบข้อมูลละเมิดลิขสิทธิ์</a> หรือแจ้งได้ที่
           <a href="http://dmca.openstreetmap.org/">หน้ารับแจ้งการละเมิดข้อมูลลิขสิทธิ์</a>
-        trademarks_title_html: <span id="trademarks"></span>เครืองหมายการค้า
+        trademarks_title_html: <span id="trademarks"></span>เครื่องหมายการค้า
+        trademarks_1_html: OpenStreetMap, State of the Map, และตราสัญลักษณ์แว่นขยาย
+          เป็นเครื่องหมายการค้าจดทะเบียนของมูลนิธิ OpenStreetMap, หากคุณมีข้อสงสัยเกี่ยวกับการใช้ชื่อและตราสัญลักษณ์ของเรา
+          สามารถตรวจสอบรายละเอียดได้ที่หน้า<a href="https://wiki.osmfoundation.org/wiki/Trademark_Policy">นโยบายเครื่องหมายการค้า</a>
     index:
       js_1: ท่านกำลังใช้เบราว์เซอร์ที่ไม่รองรับจาวาสคริปต์ หรือท่านปิดใช้งานจาวาสคริปต์
       js_2: OpenStreetMap ใช้จาวาสคริปต์ในการแสดงแผนที่
@@ -1535,6 +1546,8 @@ th:
       upload_trace: อัปโหลดรอยทาง GPS
       trace_uploaded: แฟ้มข้อมูล GPX ของท่านอัปโหลดเข้าระบบแล้ว กำลังรอบรรจุเข้าฐานข้อมูล
         ซึ่งจะใช้เวลาประมาณครึ่งชั่วโมง เมื่อกระบวนการเรียบร้อยแล้วจะมีอีเมลแจ้งท่านให้ทราบ
+      traces_waiting: คุณมีรอยทาง %{count} ชุด ที่กำลังรออัพโหลด กรุณารอให้การอัพโหลดเหล่านี้เสร็จสิ้น
+        ก่อนที่จะเพิ่มรอยทางชุดต่อไป, เพื่อไม่ให้ผู้ใช้คนอื่นๆ จะต้องรอคิวนาน
     edit:
       filename: 'ชื่อแฟ้ม:'
       download: ดาวน์โหลด
@@ -1607,6 +1620,8 @@ th:
   application:
     require_cookies:
       cookies_needed: ดูเหมือนว่าคุณปิดใช้งานคุกกี้อยู่, กรุณาเปิดใช้งานคุกกี้ในบราวเซอร์ของคุณก่อนจะดำเนินการต่อ
+    setup_user_auth:
+      blocked: คุณถูกระงับการเข้าถึง API, กรุณาเข้าระบบทางหน้าเว็บหลักหากต้องการทราบสาเหตุที่ถูกระงับในครั้งนี้
   oauth:
     authorize:
       title: อนุญาตการเข้าถึงบัญชีของคุณ
@@ -1711,6 +1726,9 @@ th:
       no account: ยังไม่ได้เป็นสมาชิก?
       account not active: ขออภัย บัญชีของท่านยังไม่เปิดใช้งาน<br/>โปรดใช้ลิงก์ที่ให้ไว้ในอีเมลตอบรับเพื่อเปิดใช้งานบัญชี
         หรือ<a href="%{reconfirm}">ขออีเมลตอบรับใหม่</a> หากสูญหาย
+      account is suspended: ขออภัย บัญชีของคุณถูกระงับการใช้งานเนื่องจากกิจกรรมที่น่าสงสัย<br/>หากต้องการพูดคุยในรายละเอียด
+        กรุณาติดต่อ<a href="%{webmaster}">ผู้ดูแลระบบ</a>
+      auth failure: ขออภัย ไม่สามารถเข้าระบบด้วยชื่อผู้ใช้และรหัสผ่านดังกล่าวได้
       openid_logo_alt: เข้าใช้งานด้วย OpenID
       auth_providers:
         openid:
@@ -1730,11 +1748,13 @@ th:
           alt: เข้าใช้งานด้วยบัญชี GitHub
         wikipedia:
           title: เข้าใช้งานด้วยวิกิพีเดีย
+          alt: เข้าสู่ระบบด้วยบัญชีวิกิพีเดีย
         yahoo:
           title: เข้าใช้งานด้วย Yahoo
           alt: เข้าใช้งานด้วย Yahoo OpenID
         wordpress:
           title: เข้าใช้งานด้วย Wordpress
+          alt: เข้าสู่ระบบด้วย Wordpress OpenID
         aol:
           title: เข้าใช้งานด้วย AOL
           alt: เข้าใช้งานด้วย AOL OpenID
@@ -1804,7 +1824,7 @@ th:
       my settings: การตั้งค่าของฉัน
       my comments: ความคิดเห็นของฉัน
       oauth settings: ตั้งค่าการอนุญาต OAuth
-      blocks on me: à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\97ีà¹\88à¸\81ีà¸\94à¸\81ัà¸\99à¸\82à¹\89าà¸\9eà¹\80à¸\88à¹\89า
+      blocks on me: à¸\81ารà¸\96ูà¸\81ระà¸\87ัà¸\9aà¸\82อà¸\87à¸\89ัà¸\99
       blocks by me: ผู้ใช้ที่ข้าพเจ้ากีดกัน
       send message: ส่งข้อความ
       diary: บันทึก
@@ -1836,8 +1856,10 @@ th:
       no nearby users: ไม่ได้มีผู้ใดแสดงตัวว่าทำแผนที่อยู่ใกล้เคียง
       role:
         administrator: คนนี้เป็นผู้ดูแลระบบ
+        moderator: ผู้ใช้นี้เป็นผู้ดูแล
+      block_history: การถูกระงับใช้งานในปัจจุบัน
       comments: ความเห็นที่เขียน
-      create_block: à¸\81ีà¸\94à¸\81ัà¸\99ผู้ใช้นี้
+      create_block: à¸£à¸°à¸\87ัà¸\9aผู้ใช้นี้
       activate_user: เปิดใช้งานผู้ใช้นี้
       deactivate_user: ปิดใช้งานผู้ใช้นี้
       confirm: ยืนยัน
@@ -1985,66 +2007,83 @@ th:
       fail: ไม่สามารถถอดถอนสถานะ `%{role}' แก่ผู้ใช้ `%{name}' โปรดตรวจสอบว่าทั้งผู้ใช้และสถานะเป็นที่ถูกต้องดีแล้ว
   user_blocks:
     model:
-      non_moderator_update: à¸\95à¹\89อà¸\87à¹\80à¸\9bà¹\87à¸\99à¸\9cูà¹\89à¸\94ูà¹\81ลระà¸\9aà¸\9aà¸\88ึà¸\87à¸\88ะสามารà¸\96สรà¹\89าà¸\87หรือà¸\9bรัà¸\9aà¸\9bรุà¸\87à¸\81ารà¸\81ีà¸\94à¸\81ัà¸\99ได้
+      non_moderator_update: à¸\88ะà¸\95à¹\89อà¸\87à¹\80à¸\9bà¹\87à¸\99à¸\9cูà¹\89à¸\94ูà¹\81ลระà¸\9aà¸\9aà¸\88ึà¸\87à¸\88ะสามารà¸\96ระà¸\87ัà¸\9a à¸«à¸£à¸·à¸­à¹\81à¸\81à¹\89à¹\84à¸\82à¸\81ารระà¸\87ัà¸\9aà¸\9cูà¹\89à¹\83à¸\8aà¹\89ได้
       non_moderator_revoke: ต้องเป็นผู้ดูแลระบบจึงจะสามารถเพิกถอนการกีดกันได้
     not_found:
-      sorry: à¸\82ออภัย à¸\81ารà¸\81ีà¸\94à¸\81ัà¸\99à¸\9cูà¹\89à¹\83à¸\8aà¹\89รหัส %{id} à¹\84มà¹\88à¸\9eà¸\9a
+      sorry: à¸\82ออภัย à¹\84มà¹\88à¸\9eà¸\9aà¸\81ารระà¸\87ัà¸\9aà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\95ามหมายà¹\80ลà¸\82อà¹\89าà¸\87อิà¸\87 %{id} à¸\97ีà¹\88ระà¸\9aุมา
       back: กลับไปที่ดัชนี
     new:
-      title: à¸ªà¸£à¹\89าà¸\87à¸\81ารà¸\81ีà¸\94à¸\81ัà¸\99à¸\9aà¸\99 %{name}
+      title: à¸£à¸°à¸\87ัà¸\9aà¸\9cูà¹\89à¹\83à¸\8aà¹\89 %{name}
       heading: สร้างการกีดกันบน %{name}
-      reason: à¹\80หà¸\95ุà¸\9cลà¸\97ีà¹\88à¸\9cูà¹\89à¹\83à¸\8aà¹\89 %{name} à¸\96ูà¸\81à¸\81ีà¸\94à¸\81ัà¸\99 à¹\82à¸\9bรà¸\94อยà¹\88าà¹\83à¸\8aà¹\89อารมà¸\93à¹\8cรุà¸\99à¹\81รà¸\87à¹\83à¸\99ระหวà¹\88าà¸\87ระà¸\9aุ
-        à¹\81ละà¸\82อà¹\83หà¹\89ระà¸\9aุรายละà¹\80อียà¸\94à¹\80à¸\81ีà¹\88ยวà¸\81ัà¸\9aสà¸\96าà¸\99à¸\81ารà¸\93à¹\8cà¸\97ีà¹\88à¸\9eà¸\9aà¹\83หà¹\89ละà¹\80อียà¸\94à¸\8aัà¸\94à¹\80à¸\88à¸\99 à¸\88ำà¹\84วà¹\89วà¹\88าà¸\82à¹\89อà¸\84วามà¸\97ีà¹\88à¸\97à¹\88าà¸\99à¸\9eิมà¸\9eà¹\8cà¸\88ะà¸\9bราà¸\81à¸\8fà¸\95à¹\88อสาà¸\98ารà¸\93ะ
-        à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\97ุà¸\81à¸\97à¹\88าà¸\99à¹\84มà¹\88à¸\88ำà¸\95à¹\89อà¸\87à¹\80à¸\82à¹\89าà¹\83à¸\88à¸\96ึà¸\87ศัà¸\9eà¸\97à¹\8cà¹\80à¸\89à¸\9eาะ à¸\88ึà¸\87à¸\82อà¹\81à¸\99ะà¸\99ำà¹\83หà¹\89à¹\83à¸\8aà¹\89ศัà¸\9eà¸\97à¹\8cอยà¹\88าà¸\87à¸\87à¹\88า
-      period: à¸\95à¹\89อà¸\87à¸\81ารà¸\81ีà¸\94à¸\81ัà¸\99à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\84à¸\99à¸\99ีà¹\89à¸\88าà¸\81 API à¸\99ัà¸\9aà¹\81à¸\95à¹\88à¸\9aัà¸\94à¸\99ีà¹\89 à¸\99าà¸\99à¹\80à¸\97à¹\88าà¹\83à¸\94
+      reason: à¹\80หà¸\95ุà¸\9cลà¸\97ีà¹\88à¸\9cูà¹\89à¹\83à¸\8aà¹\89 %{name} à¸\96ูà¸\81ระà¸\87ัà¸\9a, à¹\82à¸\9bรà¸\94อยà¹\88าà¹\80à¸\82ียà¸\99à¸\94à¹\89วยอารมà¸\93à¹\8cรุà¸\99à¹\81รà¸\87 à¹\82à¸\94ยà¸\82อà¹\83หà¹\89ระà¸\9aุรายละà¹\80อียà¸\94à¹\80à¸\81ีà¹\88ยวà¸\81ัà¸\9aสà¸\96าà¸\99à¸\81ารà¸\93à¹\8cà¸\97ีà¹\88à¸\9eà¸\9aà¹\83หà¹\89ละà¹\80อียà¸\94à¸\8aัà¸\94à¹\80à¸\88à¸\99,
+        à¸\84วรà¹\83à¸\8aà¹\89à¸\84ำอà¸\98ิà¸\9aายà¸\97ีà¹\88à¹\80à¸\82à¹\89าà¹\83à¸\88à¸\87à¹\88ายà¹\80à¸\9bà¹\87à¸\99หลัà¸\81 à¹\80à¸\9eราะà¹\84มà¹\88à¹\83à¸\8aà¹\88วà¹\88าà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\97ุà¸\81à¸\84à¸\99à¸\88ะà¹\80à¸\82à¹\89าà¹\83à¸\88ศัà¸\9eà¸\97à¹\8cà¹\80à¸\89à¸\9eาะ,
+        à¹\81ละà¸\95à¹\89อà¸\87อยà¹\88าลืม à¸§à¹\88าสิà¹\88à¸\87à¸\97ีà¹\88à¸\84ุà¸\93à¹\80à¸\82ียà¸\99à¸\99ีà¹\89à¸\88ะà¹\81สà¸\94à¸\87à¸\95à¹\88อสาà¸\98ารà¸\93ะà¸\94à¹\89ว
+      period: à¸£à¸°à¸\87ัà¸\9aà¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\84à¸\99à¸\99ีà¹\89à¸\88าà¸\81à¸\81ารà¹\80à¸\82à¹\89าà¸\96ึà¸\87 API, à¸\99าà¸\99à¹\80à¸\97à¹\88าà¹\83à¸\94 à¹\82à¸\94ยà¹\80ริà¹\88มà¸\99ัà¸\9aà¸\88าà¸\81à¸\9bัà¸\88à¸\88ุà¸\9aัà¸\99
       submit: สร้างการกีดกัน
       tried_contacting: ข้าพเจ้าติดต่อผู้ใช้คนนี้และขอร้องให้เขาหยุดการกระทำ
       tried_waiting: ข้าพเจ้าได้ให้เวลานานสมควรแก่ผู้ใช้คนนี้ในการตอบคำถามกลับ
-      needs_view: ผู้ใช้ต้องเข้าระบบก่อนการกีดกันนี้จะถูกเพิกถอน
+      needs_view: ผู้ใช้ต้องเข้าระบบก่อน การระงับนี้จึงจะถูกเพิกถอน
       back: แสดงการกีดกันทั้งหมด
     edit:
-      title: à¹\81à¸\81à¹\89à¹\84à¸\82à¸\81ารà¸\81ีà¸\94à¸\81ัà¸\99à¸\9aà¸\99 %{name}
+      title: à¹\81à¸\81à¹\89à¹\84à¸\82à¸\81ารระà¸\87ัà¸\9aà¸\9cูà¹\89à¹\83à¸\8aà¹\89 %{name}
       heading: แก้ไขการกีดกันบน %{name}
-      reason: เหตุผลที่ผู้ใช้ %{name} ถูกกีดกัน โปรดอย่าใช้อารมณ์รุนแรงในระหว่างระบุ
-        และขอให้ระบุรายละเอียดเกี่ยวกับสถานการณ์ที่พบให้ละเอียดชัดเจน จำไว้ว่าข้อความที่ท่านพิมพ์จะปรากฏต่อสาธารณะ
-        ผู้ใช้ทุกท่านไม่จำต้องเข้าใจถึงศัพท์เฉพาะ จึงขอแนะนำให้ใช้ศัพท์อย่างง่าย
-      period: ต้องการกีดกันผู้ใช้คนนี้จาก API นับแต่บัดนี้ นานเท่าใด
+      reason: เหตุผลที่ผู้ใช้ %{name} ถูกระงับ, โปรดอย่าเขียนด้วยอารมณ์รุนแรง โดยขอให้ระบุรายละเอียดเกี่ยวกับสถานการณ์ที่พบให้ละเอียดชัดเจน
+        และควรใช้คำอธิบายที่เข้าใจง่ายเป็นหลัก เพราะไม่ใช่ว่าผู้ใช้ทุกคนจะเข้าใจศัพท์เฉพาะ
+      period: ระงับผู้ใช้คนนี้จากการเข้าถึง API, นานเท่าใด โดยเริ่มนับจากปัจจุบัน
       submit: ปรับปรุงการกีดกัน
-      show: à¸\94ูà¸\81ารà¸\81ีà¸\94à¸\81ัà¸\99นี้
+      show: à¸\94ูรายละà¹\80อียà¸\94à¸\81ารระà¸\87ัà¸\9aนี้
       back: แสดงการกีดกันทั้งหมด
-      needs_view: à¸\95à¹\89อà¸\87à¸\81ารà¹\83หà¹\89à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\84à¸\99à¸\99ีà¹\89à¹\80à¸\82à¹\89าระà¸\9aà¸\9aà¸\81à¹\88อà¸\99à¹\80à¸\9eิà¸\81à¸\96อà¸\99à¸\81ารà¸\81ีà¸\94à¸\81ัà¸\99หรือไม่?
+      needs_view: à¸\95à¹\89อà¸\87à¸\81ารà¹\83หà¹\89à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\84à¸\99à¸\99ีà¹\89à¹\80à¸\82à¹\89าระà¸\9aà¸\9aà¸\81à¹\88อà¸\99à¹\80à¸\9eิà¸\81à¸\96อà¸\99à¸\81ารระà¸\87ัà¸\9aหรือไม่?
     filter:
       block_expired: การกีดกันนี้สิ้นผลแล้วแก้ไขไม่ได้
-      block_period: à¸£à¸°à¸¢à¸°à¹\80วลาà¸\97ีà¹\88à¸\81ีà¸\94à¸\81ัà¸\99à¸\95à¹\89อà¸\87à¹\80à¸\9bà¹\87à¸\99à¹\84à¸\9bà¸\95ามรายà¸\81ารà¹\80ลือà¸\81à¹\83à¸\99à¸\81ลà¹\88อà¸\87à¸\95ัวà¹\80ลือà¸\81à¹\80à¸\97à¹\88าà¸\99ัà¹\89à¸\99
+      block_period: à¸\94ูระยะà¹\80วลาà¸\97ีà¹\88ระà¸\87ัà¸\9a à¹\83หà¹\89à¹\80à¸\9bà¹\87à¸\99หà¸\99ึà¹\88à¸\87à¹\83à¸\99à¸\84à¹\88าà¸\97ีà¹\88à¹\80ลือà¸\81à¹\84วà¹\89à¸\88าà¸\81รายà¸\81ารà¸\99ีà¹\89
     create:
-      try_contacting: กรุณาติดต่อผู้ใช้ก่อนที่จะกีดกันเขาออกจากระบบ และเผื่อเวลาระยะหนึ่งให้ตอบกลับ
+      try_contacting: กรุณาติดต่อผู้ใช้คนนั้นก่อนที่จะตัดสินใจสั่งระงับใช้งาน และอย่าลืมเผื่อเวลาระยะหนึ่งให้ตอบกลับ
+      try_waiting: กรุณาให้เวลากับผู้ใช้ในการตอบคำถาม ก่อนที่ตัดสินเรื่องการสั่งระงับใช้งาน
     update:
+      only_creator_can_edit: การระงับนี้สามารถแก้ไขได้ โดยผู้ดูแลที่เป็นผู้สั่งระงับเองเท่านั้น
       success: ปรับปรุงการกีดกันแล้ว
     index:
-      title: à¸\81ารà¸\81ีà¸\94à¸\81ัà¸\99ผู้ใช้
-      heading: à¸£à¸²à¸¢à¸\81ารà¸\81ารà¸\81ีà¸\94à¸\81ัà¸\99ผู้ใช้
+      title: à¸\81ารระà¸\87ัà¸\9aผู้ใช้
+      heading: à¸£à¸²à¸¢à¸\81ารà¸\81ารระà¸\87ัà¸\9aผู้ใช้
       empty: ยังไม่มีการกีดกันใด ๆ
     revoke:
-      past: การบล็อกนี้ได้สิ้นสุดไปเมื่อ %{time}ก่อนแล้ว การยกเลิกจึงไม่มีผล
-      flash: ได้ยกเลิกการบล็อกนี้แล้ว
+      title: ยกเลิกการระงับใช้งานของ %{block_on}
+      heading: เพิกถอนการระงับผู้ใช้ %{block_on} ซึ่งสั่งโดยผู้ใช้ %{block_by}
+      past: การระงับนี้ได้สิ้นสุดไปเมื่อ %{time}ก่อนแล้ว การยกเลิกจึงไม่มีผล
+      confirm: แน่ใจหรือว่าต้องการจะยกเิลิกการระงับนี้?
+      flash: ได้ยกเลิกการระงับนี้แล้ว
     helper:
       time_future: จะสิ้นสุดใน %{time}
+      until_login: มีผลจนถึงการเริ่มเข้าระบบครั้งถัดไป
       time_past: สิ้นสุดไปเมื่อ %{time}ก่อน
     blocks_on:
-      title: การกีดกันบน %{name}
-      heading: รายการการกีดกันบน %{name}
-      empty: '%{name} ยังไม่ได้ถูกกีดกัน'
+      title: การถูกระงับใช้งานของ %{name}
+      heading: รายการการถูกระงับของผู้ใช้ %{name}
+      empty: '%{name} ยังไม่เคยถูกระงับใช้งาน'
+    blocks_by:
+      heading: แสดงการสั่งระงับใช้โดย %{name}
+      empty: '%{name} ไม่เคยได้สั่งระงับผู้ใช้คนใดเลย'
     show:
+      heading: '%{block_on} โดนระงับโดย %{block_by}'
       time_past: สิ้นสุดไปเมื่อ %{time}ก่อน
+      created: ระงับเมื่อ
       ago: '%{time}ก่อน'
       status: สถานะ
       show: แสดง
       edit: แก้ไข
+      reason: 'เหตุผลสำหรับการระงับใช้งาน:'
+      needs_view: ผู้ใช้ต้องเข้าระบบก่อน การระงับนี้จึงจะถูกเพิกถอน
     block:
+      not_revoked: (ไม่ได้มีการยกเลิก)
       show: แสดง
       edit: แก้ไข
     blocks:
+      display_name: ผู้ใช้ที่ถูกระงับ
+      creator_name: ผู้สั่งให้ระงับ
+      reason: เหตุผลที่ต้องระงับใช้งาน
       status: สถานะ
+      revoker_name: ยกเลิกโดย
       showing_page: หน้า %{page}
       next: ถัดไป »
       previous: « ก่อนหน้า
@@ -2061,6 +2100,7 @@ th:
       full: เนื้อความเต็มในหมายเหตุ
     mine:
       heading: หมายเหตุของ %{user}
+      creator: ผู้สร้าง
       ago_html: '%{when}ก่อน'
   javascripts:
     close: ปิด
@@ -2120,6 +2160,8 @@ th:
       new:
         add: เพิ่มหมายเหตุ
       show:
+        anonymous_warning: หมายเหตุนี้มีข้อความจากผู้ที่ไม่ประสงค์จะออกนาม ซึ่งควรทำการตรวจสอบตามข้อมูลที่แจ้งมานี้ด้วยตัวคุณเองอีกครั้ง
+          ก่อนจะดำเนินการใดๆ ต่อ
         hide: ซ่อน
         resolve: ปิดเรื่อง
         reactivate: รื้อฟื้นหมายเหตุ
@@ -2139,27 +2181,35 @@ th:
       directions: เส้นทาง
       distance: ระยะทาง
       errors:
+        no_route: ไม่พบเส้นทางระหว่างสองจุดที่คุณต้องการ
         no_place: ขออภัย - ไม่พบสถานที่ "%{place}"
       instructions:
         continue_without_exit: เคลื่อนต่อไปทางถนน %{name}
+        slight_right_without_exit: เบนขวาไปที่ %{name}
         offramp_right_with_name: ใช้ทางลาดด้านขวาไปที่ถนน %{name}
         onramp_right_without_exit: เลี่ยวขวาที่ทางลาดไปที่ถนน %{name}
-        endofroad_right_without_exit: à¹\80มืà¹\88อà¸\96ึà¸\87สุà¸\94à¸\96à¸\99à¸\99à¹\80ลีà¹\89ยวà¸\82วาà¹\84à¸\9bà¸\97ีà¹\88à¸\96à¸\99à¸\99 %{name}
+        endofroad_right_without_exit: à¹\80มืà¹\88อà¸\96ึà¸\87สุà¸\94à¸\96à¸\99à¸\99à¹\81ลà¹\89ว à¹\83หà¹\89à¹\80ลีà¹\89ยวà¸\82วาà¹\80à¸\82à¹\89า %{name}
         merge_right_without_exit: เลี้ยวขวาเข้าสู่ถนน %{name} ซึ่งเป็นทางเอก
         fork_right_without_exit: ที่ทางแยกเลี้ยวขวาไปที่ถนน %{name}
+        turn_right_without_exit: เลี้ยวขวาเข้า %{name}
         sharp_right_without_exit: หักขวาเข้า %{name}
         uturn_without_exit: วกกลับไปตามถนน %{name}
         sharp_left_without_exit: หักซ้ายเข้า %{name}
         turn_left_without_exit: เลี้ยวซ้ายไปที่ %{name}
         offramp_left_with_name: ใช้ทางลาดด้านซ้ายไปที่ %{name}
         onramp_left_without_exit: เลี้ยวซ้ายบนทางลาดไปที่ถนน %{name}
+        onramp_left_without_directions: เลี้ยวซ้ายขึ้นทางลาด
+        onramp_left: เลี้ยวซ้ายขึ้นทางลาด
         endofroad_left_without_exit: เมื่อถึงสุดถนนเลี้ยวซ้ายไปที่ถนน %{name}
         merge_left_without_exit: เลี้ยวซ้ายเข้าสู่ถนน %{name} ซึ่งเป็นทางเอก
         fork_left_without_exit: ที่ทางแยกเลี้ยวซ้ายไปที่ถนน %{name}
         slight_left_without_exit: ขยับซ้ายเล็กน้อยไปที่ %{name}
         follow_without_exit: ไปตาม %{name}
+        leave_roundabout_without_exit: ออกจากวงเวียน - %{name}
         start_without_exit: เริ่มที่ %{name}
         destination_without_exit: ตรงไปยังจุดหมาย
+        against_oneway_without_exit: ให้วิ่งสวนเลนไปบน %{name}
+        end_oneway_without_exit: สิ้นสุดช่วงเดินรถทางเดียวบน %{name}
         roundabout_with_exit: ณ วงเวียน ใช้ทางออก %{exit} ไปที่ถนน %{name}
         exit_roundabout: ออกจากวงเวียนไปทาง %{name}
         unnamed: ถนนไม่มีชื่อ
index 30ee46e5b34139554b087af6a4c4504d209c6218..88b920c5d63f03e3bcfff61bb2ebe5f910cd51a2 100644 (file)
@@ -1429,6 +1429,10 @@ tr:
           <strong>Avusturya</strong>: <a href="https://data.wien.gv.at/">Stadt Wien</a> (<a href="https://creativecommons.org/licenses/by/3.0/at/deed.de">CC BY</a> lisansı altında),
           <a href="https://www.vorarlberg.at/vorarlberg/bauen_wohnen/bauen/vermessung_geoinformation/weitereinformationen/services/wmsdienste.htm">Land Vorarlberg</a> ve
           Land Tirol'dan (<a href="https://www.tirol.gv.at/applikationen/e-government/data/nutzungsbedingungen/">değişiklikleriyle CC BY AT lisansı altında</a>) veriler içermektedir.
+        contributors_au_html: '<strong>Avustralya</strong>: <a href="https://creativecommons.org/licenses/by/4.0/">CC
+          BY 4.0</a> kapsamında Commonwealth of Australia tarafından lisanslanan <a
+          href="https://creativecommons.org/licenses/by/4.0/">PSMA Australia Limited</a>''ten
+          alınan verileri içerir.'
         contributors_ca_html: "<strong>Kanada</strong>: GeoBase&reg;, GeoGratis \n(&copy;
           Department of Natural\nResources Canada), CanVec (&copy; Department of Natural\nResources
           Canada) ve StatCan'den (Geography Division,\nStatistics Canada) veriler
@@ -2637,6 +2641,8 @@ tr:
           %{name} yoluna doğru alın.
         onramp_right_without_exit: Rampadan sağa dönerek %{name} girin
         onramp_right_with_directions: '%{directions} doğru rampadan sağ dönün'
+        onramp_right_with_name_directions: '%{name} üzerindeki rampaya doğru %{directions}
+          yönünde sağa dönün'
         onramp_right_without_directions: Rampaya doğru sağa dönün
         onramp_right: Rampaya doğru sağa dönün
         endofroad_right_without_exit: Yolun sonunda sağa %{name} yönünde dönün
@@ -2656,8 +2662,12 @@ tr:
           %{directions} yönüne doğru'
         offramp_left_with_name: Soldaki rampayı kullanarak %{name} girin
         offramp_left_with_directions: '%{directions} yönünde soldaki rampadan'
+        offramp_left_with_name_directions: '%{name} üzerindeki rampaya doğru %{directions}
+          yönünde sola ilerleyin'
         onramp_left_without_exit: Rampadan sola dönerek %{name} girin
         onramp_left_with_directions: '%{directions} doğru rampadan sola dönün'
+        onramp_left_with_name_directions: '%{name} üzerindeki rampaya doğru %{directions}
+          yönünde sola dönün'
         onramp_left_without_directions: Rampaya doğru sola dönün
         onramp_left: Rampaya doğru sola dönün
         endofroad_left_without_exit: Yolun sonunda sola %{name} yönünde dönün
diff --git a/db/migrate/20181031113522_create_delayed_jobs.rb b/db/migrate/20181031113522_create_delayed_jobs.rb
new file mode 100644 (file)
index 0000000..69c6f1b
--- /dev/null
@@ -0,0 +1,22 @@
+class CreateDelayedJobs < ActiveRecord::Migration[5.2]
+  def self.up
+    create_table :delayed_jobs, :force => true do |table|
+      table.integer :priority, :default => 0, :null => false # Allows some jobs to jump to the front of the queue
+      table.integer :attempts, :default => 0, :null => false # Provides for retries, but still fail eventually.
+      table.text :handler,                    :null => false # YAML-encoded string of the object that will do work
+      table.text :last_error                                 # reason for last failure (See Note below)
+      table.datetime :run_at                                 # When to run. Could be Time.zone.now for immediately, or sometime in the future.
+      table.datetime :locked_at                              # Set when a client is working on this object
+      table.datetime :failed_at                              # Set when all retries have failed (actually, by default, the record is deleted instead)
+      table.string :locked_by                                # Who is working on this object (if locked)
+      table.string :queue                                    # The name of the queue this job is in
+      table.timestamps :null => true
+    end
+
+    add_index :delayed_jobs, [:priority, :run_at], :name => "delayed_jobs_priority"
+  end
+
+  def self.down
+    drop_table :delayed_jobs
+  end
+end
index 48fedeba56b65d1247762f7a35eb29f9a5a1b98b..dcab302bb1c05f943ebe14319e2d7ada68ef7cb0 100644 (file)
@@ -494,6 +494,45 @@ CREATE SEQUENCE current_ways_id_seq
 ALTER SEQUENCE current_ways_id_seq OWNED BY current_ways.id;
 
 
+--
+-- Name: delayed_jobs; Type: TABLE; Schema: public; Owner: -
+--
+
+CREATE TABLE delayed_jobs (
+    id bigint NOT NULL,
+    priority integer DEFAULT 0 NOT NULL,
+    attempts integer DEFAULT 0 NOT NULL,
+    handler text NOT NULL,
+    last_error text,
+    run_at timestamp without time zone,
+    locked_at timestamp without time zone,
+    failed_at timestamp without time zone,
+    locked_by character varying,
+    queue character varying,
+    created_at timestamp without time zone,
+    updated_at timestamp without time zone
+);
+
+
+--
+-- Name: delayed_jobs_id_seq; Type: SEQUENCE; Schema: public; Owner: -
+--
+
+CREATE SEQUENCE delayed_jobs_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
+
+
+--
+-- Name: delayed_jobs_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
+--
+
+ALTER SEQUENCE delayed_jobs_id_seq OWNED BY delayed_jobs.id;
+
+
 --
 -- Name: diary_comments; Type: TABLE; Schema: public; Owner: -
 --
@@ -1365,6 +1404,13 @@ ALTER TABLE ONLY current_relations ALTER COLUMN id SET DEFAULT nextval('current_
 ALTER TABLE ONLY current_ways ALTER COLUMN id SET DEFAULT nextval('current_ways_id_seq'::regclass);
 
 
+--
+-- Name: delayed_jobs id; Type: DEFAULT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY delayed_jobs ALTER COLUMN id SET DEFAULT nextval('delayed_jobs_id_seq'::regclass);
+
+
 --
 -- Name: diary_comments id; Type: DEFAULT; Schema: public; Owner: -
 --
@@ -1595,6 +1641,14 @@ ALTER TABLE ONLY current_ways
     ADD CONSTRAINT current_ways_pkey PRIMARY KEY (id);
 
 
+--
+-- Name: delayed_jobs delayed_jobs_pkey; Type: CONSTRAINT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY delayed_jobs
+    ADD CONSTRAINT delayed_jobs_pkey PRIMARY KEY (id);
+
+
 --
 -- Name: diary_comments diary_comments_pkey; Type: CONSTRAINT; Schema: public; Owner: -
 --
@@ -1918,6 +1972,13 @@ CREATE INDEX current_way_nodes_node_idx ON current_way_nodes USING btree (node_i
 CREATE INDEX current_ways_timestamp_idx ON current_ways USING btree ("timestamp");
 
 
+--
+-- Name: delayed_jobs_priority; Type: INDEX; Schema: public; Owner: -
+--
+
+CREATE INDEX delayed_jobs_priority ON delayed_jobs USING btree (priority, run_at);
+
+
 --
 -- Name: diary_comment_user_id_created_at_index; Type: INDEX; Schema: public; Owner: -
 --
@@ -2870,6 +2931,7 @@ INSERT INTO "schema_migrations" (version) VALUES
 ('20161011010929'),
 ('20170222134109'),
 ('20180204153242'),
+('20181031113522'),
 ('21'),
 ('22'),
 ('23'),
index 811d09239d0fe5a325e3aca04204d86470434af5..dbeaf5a408e66dfd757b6d63fb5ea639a49c44bc 100644 (file)
@@ -67,17 +67,17 @@ module ActionController
       DEFAULT_OPTIONS = {
         :class_name => nil,
         :singular_name => nil,
-        :per_page   => 10,
+        :per_page => 10,
         :conditions => nil,
-        :order_by   => nil,
-        :order      => nil,
-        :join       => nil,
-        :joins      => nil,
-        :count      => nil,
-        :include    => nil,
-        :select     => nil,
-        :group      => nil,
-        :parameter  => "page"
+        :order_by => nil,
+        :order => nil,
+        :join => nil,
+        :joins => nil,
+        :count => nil,
+        :include => nil,
+        :select => nil,
+        :group => nil,
+        :parameter => "page"
       }.freeze
     end
 
index cb553bfbcad71a095c0940f61b3fb5341d1d4712..e3c533b7af6e8357a1a6b821792b2da6cbb0e3df 100644 (file)
@@ -8,8 +8,8 @@ class DiffReader
 
   # maps each element type to the model class which handles it
   MODELS = {
-    "node"     => Node,
-    "way"      => Way,
+    "node" => Node,
+    "way" => Way,
     "relation" => Relation
   }.freeze
 
index 53252b769739f835a351fb26ce04cbd5601d0879..954acbf227dc1a6309c5d47ff341d9e249ae9f3b 100644 (file)
@@ -6,41 +6,41 @@ if Rails.env.development?
     # You can override any of these by setting an environment variable of the
     # same name.
     Annotate.set_defaults(
-      "routes"                  => "false",
-      "position_in_routes"      => "before",
-      "position_in_class"       => "before",
-      "position_in_test"        => "before",
-      "position_in_fixture"     => "before",
-      "position_in_factory"     => "before",
-      "position_in_serializer"  => "before",
-      "show_foreign_keys"       => "true",
-      "show_indexes"            => "true",
-      "simple_indexes"          => "false",
-      "model_dir"               => "app/models",
-      "root_dir"                => "",
-      "include_version"         => "false",
-      "require"                 => "",
-      "exclude_tests"           => "true",
-      "exclude_fixtures"        => "true",
-      "exclude_factories"       => "true",
-      "exclude_serializers"     => "true",
-      "exclude_scaffolds"       => "true",
-      "exclude_controllers"     => "true",
-      "exclude_helpers"         => "true",
-      "ignore_model_sub_dir"    => "false",
-      "ignore_columns"          => nil,
-      "ignore_routes"           => nil,
-      "ignore_unknown_models"   => "false",
+      "routes" => "false",
+      "position_in_routes" => "before",
+      "position_in_class" => "before",
+      "position_in_test" => "before",
+      "position_in_fixture" => "before",
+      "position_in_factory" => "before",
+      "position_in_serializer" => "before",
+      "show_foreign_keys" => "true",
+      "show_indexes" => "true",
+      "simple_indexes" => "false",
+      "model_dir" => "app/models",
+      "root_dir" => "",
+      "include_version" => "false",
+      "require" => "",
+      "exclude_tests" => "true",
+      "exclude_fixtures" => "true",
+      "exclude_factories" => "true",
+      "exclude_serializers" => "true",
+      "exclude_scaffolds" => "true",
+      "exclude_controllers" => "true",
+      "exclude_helpers" => "true",
+      "ignore_model_sub_dir" => "false",
+      "ignore_columns" => nil,
+      "ignore_routes" => nil,
+      "ignore_unknown_models" => "false",
       "hide_limit_column_types" => "integer,boolean",
-      "skip_on_db_migrate"      => "false",
-      "format_bare"             => "true",
-      "format_rdoc"             => "false",
-      "format_markdown"         => "false",
-      "sort"                    => "false",
-      "force"                   => "false",
-      "trace"                   => "false",
-      "wrapper_open"            => nil,
-      "wrapper_close"           => nil
+      "skip_on_db_migrate" => "false",
+      "format_bare" => "true",
+      "format_rdoc" => "false",
+      "format_markdown" => "false",
+      "sort" => "false",
+      "force" => "false",
+      "trace" => "false",
+      "wrapper_open" => nil,
+      "wrapper_close" => nil
     )
   end
 
diff --git a/test/abilities/abilities_test.rb b/test/abilities/abilities_test.rb
new file mode 100644 (file)
index 0000000..fc37b0e
--- /dev/null
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require "test_helper"
+
+class AbilityTest < ActiveSupport::TestCase
+end
+
+class GuestAbilityTest < AbilityTest
+  test "geocoder permission for a guest" do
+    ability = Ability.new nil
+
+    [:search, :search_latlon, :search_ca_postcode, :search_osm_nominatim,
+     :search_geonames, :search_osm_nominatim_reverse, :search_geonames_reverse].each do |action|
+      assert ability.can?(action, :geocoder), "should be able to #{action} geocoder"
+    end
+  end
+
+  test "diary permissions for a guest" do
+    ability = Ability.new nil
+    [:index, :rss, :show, :comments].each do |action|
+      assert ability.can?(action, DiaryEntry), "should be able to #{action} DiaryEntries"
+    end
+
+    [:create, :edit, :comment, :subscribe, :unsubscribe, :hide, :hidecomment].each do |action|
+      assert ability.cannot?(action, DiaryEntry), "should not be able to #{action} DiaryEntries"
+      assert ability.cannot?(action, DiaryComment), "should not be able to #{action} DiaryEntries"
+    end
+  end
+end
+
+class UserAbilityTest < AbilityTest
+  test "Diary permissions" do
+    ability = Ability.new create(:user)
+
+    [:index, :rss, :show, :comments, :create, :edit, :comment, :subscribe, :unsubscribe].each do |action|
+      assert ability.can?(action, DiaryEntry), "should be able to #{action} DiaryEntries"
+    end
+
+    [:hide, :hidecomment].each do |action|
+      assert ability.cannot?(action, DiaryEntry), "should not be able to #{action} DiaryEntries"
+      assert ability.cannot?(action, DiaryComment), "should not be able to #{action} DiaryEntries"
+    end
+
+    [:index, :show, :resolve, :ignore, :reopen].each do |action|
+      assert ability.cannot?(action, Issue), "should not be able to #{action} Issues"
+    end
+  end
+end
+
+class ModeratorAbilityTest < AbilityTest
+  test "Issue permissions" do
+    ability = Ability.new create(:moderator_user)
+
+    [:index, :show, :resolve, :ignore, :reopen].each do |action|
+      assert ability.can?(action, Issue), "should be able to #{action} Issues"
+    end
+  end
+end
+
+class AdministratorAbilityTest < AbilityTest
+  test "Diary for an administrator" do
+    ability = Ability.new create(:administrator_user)
+    [:index, :rss, :show, :comments, :create, :edit, :comment, :subscribe, :unsubscribe, :hide, :hidecomment].each do |action|
+      assert ability.can?(action, DiaryEntry), "should be able to #{action} DiaryEntries"
+    end
+
+    [:hide, :hidecomment].each do |action|
+      assert ability.can?(action, DiaryComment), "should be able to #{action} DiaryComment"
+    end
+  end
+end
diff --git a/test/abilities/capability_test.rb b/test/abilities/capability_test.rb
new file mode 100644 (file)
index 0000000..a25c670
--- /dev/null
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require "test_helper"
+
+class CapabilityTest < ActiveSupport::TestCase
+  def tokens(*toks)
+    AccessToken.new do |token|
+      toks.each do |t|
+        token.public_send("#{t}=", true)
+      end
+    end
+  end
+end
+
+class UserCapabilityTest < CapabilityTest
+  test "user preferences" do
+    # a user with no tokens
+    capability = Capability.new nil
+    [:read, :read_one, :update, :update_one, :delete_one].each do |act|
+      assert capability.cannot? act, UserPreference
+    end
+
+    # A user with empty tokens
+    capability = Capability.new tokens
+
+    [:read, :read_one, :update, :update_one, :delete_one].each do |act|
+      assert capability.cannot? act, UserPreference
+    end
+
+    capability = Capability.new tokens(:allow_read_prefs)
+
+    [:update, :update_one, :delete_one].each do |act|
+      assert capability.cannot? act, UserPreference
+    end
+
+    [:read, :read_one].each do |act|
+      assert capability.can? act, UserPreference
+    end
+
+    capability = Capability.new tokens(:allow_write_prefs)
+    [:read, :read_one].each do |act|
+      assert capability.cannot? act, UserPreference
+    end
+
+    [:update, :update_one, :delete_one].each do |act|
+      assert capability.can? act, UserPreference
+    end
+  end
+end
index 0bdd01bd2e5f2209d22997d176c9007dbfdaffd1..650bf1f8ef031a3b8e19808dd2b32a58e45abb42 100644 (file)
@@ -360,11 +360,11 @@ class AmfControllerTest < ActionController::TestCase
   # into the method args.
   def test_getway_old_invalid
     way_id = create(:way, :with_history, :version => 2).id
-    { "foo"  => "bar",
+    { "foo" => "bar",
       way_id => "not a date",
       way_id => "2009-03-25 00:00:00",                   # <- wrong format
       way_id => "0 Jan 2009 00:00:00",                   # <- invalid date
-      -1     => "1 Jan 2009 00:00:00" }.each do |id, t|  # <- invalid
+      -1 => "1 Jan 2009 00:00:00" }.each do |id, t| # <- invalid
       amf_content "getway_old", "/1", [id, t]
       post :amf_read
       assert_response :success
index 2cda68b128045473d9dbfe662b300e1947337114..fdb689978f7fc1cebbc9dad700d81457204af10b 100644 (file)
@@ -2153,7 +2153,9 @@ CHANGESET
 
     assert_difference "ChangesetComment.count", 1 do
       assert_no_difference "ActionMailer::Base.deliveries.size" do
-        post :comment, :params => { :id => private_user_closed_changeset.id, :text => "This is a comment" }
+        perform_enqueued_jobs do
+          post :comment, :params => { :id => private_user_closed_changeset.id, :text => "This is a comment" }
+        end
       end
     end
     assert_response :success
@@ -2166,7 +2168,9 @@ CHANGESET
 
     assert_difference "ChangesetComment.count", 1 do
       assert_difference "ActionMailer::Base.deliveries.size", 1 do
-        post :comment, :params => { :id => changeset.id, :text => "This is a comment" }
+        perform_enqueued_jobs do
+          post :comment, :params => { :id => changeset.id, :text => "This is a comment" }
+        end
       end
     end
     assert_response :success
@@ -2182,7 +2186,9 @@ CHANGESET
 
     assert_difference "ChangesetComment.count", 1 do
       assert_difference "ActionMailer::Base.deliveries.size", 2 do
-        post :comment, :params => { :id => changeset.id, :text => "This is a comment" }
+        perform_enqueued_jobs do
+          post :comment, :params => { :id => changeset.id, :text => "This is a comment" }
+        end
       end
     end
     assert_response :success
index f28bef6feae5a2df6d77e1c6b7d749796e04088d..cec2250476fe17e8c89668f79f90314544261032 100644 (file)
@@ -390,9 +390,11 @@ class DiaryEntryControllerTest < ActionController::TestCase
     assert_no_difference "ActionMailer::Base.deliveries.size" do
       assert_no_difference "DiaryComment.count" do
         assert_no_difference "entry.subscribers.count" do
-          post :comment,
-               :params => { :display_name => entry.user.display_name, :id => entry.id, :diary_comment => { :body => "" } },
-               :session => { :user => other_user }
+          perform_enqueued_jobs do
+            post :comment,
+                 :params => { :display_name => entry.user.display_name, :id => entry.id, :diary_comment => { :body => "" } },
+                 :session => { :user => other_user }
+          end
         end
       end
     end
@@ -403,9 +405,11 @@ class DiaryEntryControllerTest < ActionController::TestCase
     assert_difference "ActionMailer::Base.deliveries.size", entry.subscribers.count do
       assert_difference "DiaryComment.count", 1 do
         assert_difference "entry.subscribers.count", 1 do
-          post :comment,
-               :params => { :display_name => entry.user.display_name, :id => entry.id, :diary_comment => { :body => "New comment" } },
-               :session => { :user => other_user }
+          perform_enqueued_jobs do
+            post :comment,
+                 :params => { :display_name => entry.user.display_name, :id => entry.id, :diary_comment => { :body => "New comment" } },
+                 :session => { :user => other_user }
+          end
         end
       end
     end
@@ -450,9 +454,11 @@ class DiaryEntryControllerTest < ActionController::TestCase
     # Try creating a spammy comment
     assert_difference "ActionMailer::Base.deliveries.size", 1 do
       assert_difference "DiaryComment.count", 1 do
-        post :comment,
-             :params => { :display_name => entry.user.display_name, :id => entry.id, :diary_comment => { :body => spammy_text } },
-             :session => { :user => other_user }
+        perform_enqueued_jobs do
+          post :comment,
+               :params => { :display_name => entry.user.display_name, :id => entry.id, :diary_comment => { :body => spammy_text } },
+               :session => { :user => other_user }
+        end
       end
     end
     assert_response :redirect
index 0b3a59b395310709e35e7199dc9eccde82edcae9..8e4d5eeb27fd0f4cd062c2dc7627fa5dea2997cd 100644 (file)
@@ -83,9 +83,11 @@ class MessagesControllerTest < ActionController::TestCase
     # Check that we can't send a message from a GET request
     assert_difference "ActionMailer::Base.deliveries.size", 0 do
       assert_difference "Message.count", 0 do
-        get :new,
-            :params => { :display_name => recipient_user.display_name,
-                         :message => { :title => "Test Message", :body => "Test message body" } }
+        perform_enqueued_jobs do
+          get :new,
+              :params => { :display_name => recipient_user.display_name,
+                           :message => { :title => "Test Message", :body => "Test message body" } }
+        end
       end
     end
     assert_response :success
@@ -112,9 +114,11 @@ class MessagesControllerTest < ActionController::TestCase
     # Check that the subject is preserved over errors
     assert_difference "ActionMailer::Base.deliveries.size", 0 do
       assert_difference "Message.count", 0 do
-        post :new,
-             :params => { :display_name => recipient_user.display_name,
-                          :message => { :title => "Test Message", :body => "" } }
+        perform_enqueued_jobs do
+          post :new,
+               :params => { :display_name => recipient_user.display_name,
+                            :message => { :title => "Test Message", :body => "" } }
+        end
       end
     end
     assert_response :success
@@ -141,9 +145,11 @@ class MessagesControllerTest < ActionController::TestCase
     # Check that the body text is preserved over errors
     assert_difference "ActionMailer::Base.deliveries.size", 0 do
       assert_difference "Message.count", 0 do
-        post :new,
-             :params => { :display_name => recipient_user.display_name,
-                          :message => { :title => "", :body => "Test message body" } }
+        perform_enqueued_jobs do
+          post :new,
+               :params => { :display_name => recipient_user.display_name,
+                            :message => { :title => "", :body => "Test message body" } }
+        end
       end
     end
     assert_response :success
@@ -170,9 +176,11 @@ class MessagesControllerTest < ActionController::TestCase
     # Check that sending a message works
     assert_difference "ActionMailer::Base.deliveries.size", 1 do
       assert_difference "Message.count", 1 do
-        post :create,
-             :params => { :display_name => recipient_user.display_name,
-                          :message => { :title => "Test Message", :body => "Test message body" } }
+        perform_enqueued_jobs do
+          post :create,
+               :params => { :display_name => recipient_user.display_name,
+                            :message => { :title => "Test Message", :body => "Test message body" } }
+        end
       end
     end
     assert_redirected_to inbox_messages_path
@@ -211,12 +219,14 @@ class MessagesControllerTest < ActionController::TestCase
     assert_no_difference "ActionMailer::Base.deliveries.size" do
       assert_no_difference "Message.count" do
         with_message_limit(0) do
-          post :create,
-               :params => { :display_name => recipient_user.display_name,
-                            :message => { :title => "Test Message", :body => "Test message body" } }
-          assert_response :success
-          assert_template "new"
-          assert_select ".error", /wait a while/
+          perform_enqueued_jobs do
+            post :create,
+                 :params => { :display_name => recipient_user.display_name,
+                              :message => { :title => "Test Message", :body => "Test message body" } }
+            assert_response :success
+            assert_template "new"
+            assert_select ".error", /wait a while/
+          end
         end
       end
     end
index 33261c412b5141b848e6f6514a7d215b2e469cd0..a1c32333224337f95e238c024d540fa222d1fb42 100644 (file)
@@ -228,7 +228,9 @@ class NotesControllerTest < ActionController::TestCase
     open_note_with_comment = create(:note_with_comments)
     assert_difference "NoteComment.count", 1 do
       assert_no_difference "ActionMailer::Base.deliveries.size" do
-        post :comment, :params => { :id => open_note_with_comment.id, :text => "This is an additional comment", :format => "json" }
+        perform_enqueued_jobs do
+          post :comment, :params => { :id => open_note_with_comment.id, :text => "This is an additional comment", :format => "json" }
+        end
       end
     end
     assert_response :success
@@ -265,7 +267,9 @@ class NotesControllerTest < ActionController::TestCase
     end
     assert_difference "NoteComment.count", 1 do
       assert_difference "ActionMailer::Base.deliveries.size", 2 do
-        post :comment, :params => { :id => note_with_comments_by_users.id, :text => "This is an additional comment", :format => "json" }
+        perform_enqueued_jobs do
+          post :comment, :params => { :id => note_with_comments_by_users.id, :text => "This is an additional comment", :format => "json" }
+        end
       end
     end
     assert_response :success
@@ -307,7 +311,9 @@ class NotesControllerTest < ActionController::TestCase
 
     assert_difference "NoteComment.count", 1 do
       assert_difference "ActionMailer::Base.deliveries.size", 2 do
-        post :comment, :params => { :id => note_with_comments_by_users.id, :text => "This is an additional comment", :format => "json" }
+        perform_enqueued_jobs do
+          post :comment, :params => { :id => note_with_comments_by_users.id, :text => "This is an additional comment", :format => "json" }
+        end
       end
     end
     assert_response :success
index ce64310cb45734bbc66603f8a9561dbfde21fdfc..20a04e90b86d50f9eb47658c4a9afd8898b20fef 100644 (file)
@@ -237,7 +237,9 @@ class UsersControllerTest < ActionController::TestCase
 
     assert_difference "User.count", 1 do
       assert_difference "ActionMailer::Base.deliveries.size", 1 do
-        post :save, :session => { :new_user => user }
+        perform_enqueued_jobs do
+          post :save, :session => { :new_user => user }
+        end
       end
     end
 
@@ -259,7 +261,9 @@ class UsersControllerTest < ActionController::TestCase
 
     assert_no_difference "User.count" do
       assert_no_difference "ActionMailer::Base.deliveries.size" do
-        post :save, :session => { :new_user => user }
+        perform_enqueued_jobs do
+          post :save, :session => { :new_user => user }
+        end
       end
     end
 
@@ -274,7 +278,9 @@ class UsersControllerTest < ActionController::TestCase
 
     assert_no_difference "User.count" do
       assert_no_difference "ActionMailer::Base.deliveries.size" do
-        post :save, :session => { :new_user => user }
+        perform_enqueued_jobs do
+          post :save, :session => { :new_user => user }
+        end
       end
     end
 
@@ -289,7 +295,9 @@ class UsersControllerTest < ActionController::TestCase
 
     assert_no_difference "User.count" do
       assert_no_difference "ActionMailer::Base.deliveries.size" do
-        post :save, :session => { :new_user => user }
+        perform_enqueued_jobs do
+          post :save, :session => { :new_user => user }
+        end
       end
     end
 
@@ -304,7 +312,9 @@ class UsersControllerTest < ActionController::TestCase
 
     assert_no_difference "User.count" do
       assert_no_difference "ActionMailer::Base.deliveries.size" do
-        post :save, :session => { :new_user => user }
+        perform_enqueued_jobs do
+          post :save, :session => { :new_user => user }
+        end
       end
     end
 
@@ -318,8 +328,10 @@ class UsersControllerTest < ActionController::TestCase
 
     assert_difference "User.count", 1 do
       assert_difference "ActionMailer::Base.deliveries.size", 1 do
-        post :save, :session => { :new_user => user,
-                                  :referer => "/edit?editor=id#map=1/2/3" }
+        perform_enqueued_jobs do
+          post :save, :session => { :new_user => user,
+                                    :referer => "/edit?editor=id#map=1/2/3" }
+        end
       end
     end
 
@@ -489,7 +501,9 @@ class UsersControllerTest < ActionController::TestCase
     session[:token] = user.tokens.create.token
 
     assert_difference "ActionMailer::Base.deliveries.size", 1 do
-      get :confirm_resend, :params => { :display_name => user.display_name }
+      perform_enqueued_jobs do
+        get :confirm_resend, :params => { :display_name => user.display_name }
+      end
     end
 
     assert_response :redirect
@@ -506,7 +520,9 @@ class UsersControllerTest < ActionController::TestCase
   def test_confirm_resend_no_token
     user = create(:user, :pending)
     assert_no_difference "ActionMailer::Base.deliveries.size" do
-      get :confirm_resend, :params => { :display_name => user.display_name }
+      perform_enqueued_jobs do
+        get :confirm_resend, :params => { :display_name => user.display_name }
+      end
     end
 
     assert_response :redirect
@@ -516,7 +532,9 @@ class UsersControllerTest < ActionController::TestCase
 
   def test_confirm_resend_unknown_user
     assert_no_difference "ActionMailer::Base.deliveries.size" do
-      get :confirm_resend, :params => { :display_name => "No Such User" }
+      perform_enqueued_jobs do
+        get :confirm_resend, :params => { :display_name => "No Such User" }
+      end
     end
 
     assert_response :redirect
@@ -674,7 +692,9 @@ class UsersControllerTest < ActionController::TestCase
     uppercase_user = build(:user, :email => user.email.upcase).tap { |u| u.save(:validate => false) }
 
     assert_difference "ActionMailer::Base.deliveries.size", 1 do
-      post :lost_password, :params => { :user => { :email => user.email } }
+      perform_enqueued_jobs do
+        post :lost_password, :params => { :user => { :email => user.email } }
+      end
     end
     assert_response :redirect
     assert_redirected_to :action => :login
@@ -687,7 +707,9 @@ class UsersControllerTest < ActionController::TestCase
     # Test resetting using an address that matches a different user
     # that has the same address in a different case
     assert_difference "ActionMailer::Base.deliveries.size", 1 do
-      post :lost_password, :params => { :user => { :email => user.email.upcase } }
+      perform_enqueued_jobs do
+        post :lost_password, :params => { :user => { :email => user.email.upcase } }
+      end
     end
     assert_response :redirect
     assert_redirected_to :action => :login
@@ -700,7 +722,9 @@ class UsersControllerTest < ActionController::TestCase
     # Test resetting using an address that is a case insensitive match
     # for more than one user but not an exact match for either
     assert_no_difference "ActionMailer::Base.deliveries.size" do
-      post :lost_password, :params => { :user => { :email => user.email.titlecase } }
+      perform_enqueued_jobs do
+        post :lost_password, :params => { :user => { :email => user.email.titlecase } }
+      end
     end
     assert_response :success
     assert_template :lost_password
@@ -710,7 +734,9 @@ class UsersControllerTest < ActionController::TestCase
     # address which is case insensitively unique
     third_user = create(:user)
     assert_difference "ActionMailer::Base.deliveries.size", 1 do
-      post :lost_password, :params => { :user => { :email => third_user.email } }
+      perform_enqueued_jobs do
+        post :lost_password, :params => { :user => { :email => third_user.email } }
+      end
     end
     assert_response :redirect
     assert_redirected_to :action => :login
@@ -723,7 +749,9 @@ class UsersControllerTest < ActionController::TestCase
     # Test resetting using an address that matches a user that has the
     # same (case insensitively unique) address in a different case
     assert_difference "ActionMailer::Base.deliveries.size", 1 do
-      post :lost_password, :params => { :user => { :email => third_user.email.upcase } }
+      perform_enqueued_jobs do
+        post :lost_password, :params => { :user => { :email => third_user.email.upcase } }
+      end
     end
     assert_response :redirect
     assert_redirected_to :action => :login
@@ -898,7 +926,9 @@ class UsersControllerTest < ActionController::TestCase
     # Changing email to one that exists should fail
     user.new_email = create(:user).email
     assert_no_difference "ActionMailer::Base.deliveries.size" do
-      post :account, :params => { :display_name => user.display_name, :user => user.attributes }, :session => { :user => user }
+      perform_enqueued_jobs do
+        post :account, :params => { :display_name => user.display_name, :user => user.attributes }, :session => { :user => user }
+      end
     end
     assert_response :success
     assert_template :account
@@ -909,7 +939,9 @@ class UsersControllerTest < ActionController::TestCase
     # Changing email to one that exists should fail, regardless of case
     user.new_email = create(:user).email.upcase
     assert_no_difference "ActionMailer::Base.deliveries.size" do
-      post :account, :params => { :display_name => user.display_name, :user => user.attributes }, :session => { :user => user }
+      perform_enqueued_jobs do
+        post :account, :params => { :display_name => user.display_name, :user => user.attributes }, :session => { :user => user }
+      end
     end
     assert_response :success
     assert_template :account
@@ -920,7 +952,9 @@ class UsersControllerTest < ActionController::TestCase
     # Changing email to one that doesn't exist should work
     user.new_email = "new_tester@example.com"
     assert_difference "ActionMailer::Base.deliveries.size", 1 do
-      post :account, :params => { :display_name => user.display_name, :user => user.attributes }, :session => { :user => user }
+      perform_enqueued_jobs do
+        post :account, :params => { :display_name => user.display_name, :user => user.attributes }, :session => { :user => user }
+      end
     end
     assert_response :success
     assert_template :account
@@ -941,8 +975,9 @@ class UsersControllerTest < ActionController::TestCase
     assert_response :not_found
 
     # Test a normal user
-    user = create(:user)
-    create(:friend, :befriender => user)
+    user = create(:user, :home_lon => 1.1, :home_lat => 1.1)
+    friend_user = create(:user, :home_lon => 1.2, :home_lat => 1.2)
+    create(:friend, :befriender => user, :befriendee => friend_user)
     get :show, :params => { :display_name => user.display_name }
     assert_response :success
     assert_select "div#userinformation" do
@@ -1257,7 +1292,9 @@ class UsersControllerTest < ActionController::TestCase
 
     # When logged in a POST should add the friendship
     assert_difference "ActionMailer::Base.deliveries.size", 1 do
-      post :make_friend, :params => { :display_name => friend.display_name }, :session => { :user => user }
+      perform_enqueued_jobs do
+        post :make_friend, :params => { :display_name => friend.display_name }, :session => { :user => user }
+      end
     end
     assert_redirected_to user_path(friend)
     assert_match(/is now your friend/, flash[:notice])
@@ -1269,7 +1306,9 @@ class UsersControllerTest < ActionController::TestCase
 
     # A second POST should report that the friendship already exists
     assert_no_difference "ActionMailer::Base.deliveries.size" do
-      post :make_friend, :params => { :display_name => friend.display_name }, :session => { :user => user }
+      perform_enqueued_jobs do
+        post :make_friend, :params => { :display_name => friend.display_name }, :session => { :user => user }
+      end
     end
     assert_redirected_to user_path(friend)
     assert_match(/You are already friends with/, flash[:warning])
@@ -1296,7 +1335,9 @@ class UsersControllerTest < ActionController::TestCase
 
     # When logged in a POST should add the friendship and refer us
     assert_difference "ActionMailer::Base.deliveries.size", 1 do
-      post :make_friend, :params => { :display_name => friend.display_name, :referer => "/test" }, :session => { :user => user }
+      perform_enqueued_jobs do
+        post :make_friend, :params => { :display_name => friend.display_name, :referer => "/test" }, :session => { :user => user }
+      end
     end
     assert_redirected_to "/test"
     assert_match(/is now your friend/, flash[:notice])
index 555e579f4926192695d9c9a08734afe53e31ae5d..144a45a45ad990af426dd413dc8f62164da1e96f 100644 (file)
@@ -37,9 +37,11 @@ class UserCreationTest < ActionDispatch::IntegrationTest
       display_name = "#{locale}_new_tester"
       assert_difference("User.count", 0) do
         assert_difference("ActionMailer::Base.deliveries.size", 0) do
-          post "/user/new",
-               :params => { :user => { :email => dup_email, :email_confirmation => dup_email, :display_name => display_name, :pass_crypt => "testtest", :pass_crypt_confirmation => "testtest" } },
-               :headers => { "HTTP_ACCEPT_LANGUAGE" => locale.to_s }
+          perform_enqueued_jobs do
+            post "/user/new",
+                 :params => { :user => { :email => dup_email, :email_confirmation => dup_email, :display_name => display_name, :pass_crypt => "testtest", :pass_crypt_confirmation => "testtest" } },
+                 :headers => { "HTTP_ACCEPT_LANGUAGE" => locale.to_s }
+          end
         end
       end
       assert_response :success
@@ -56,9 +58,11 @@ class UserCreationTest < ActionDispatch::IntegrationTest
       email = "#{locale}_new_tester"
       assert_difference("User.count", 0) do
         assert_difference("ActionMailer::Base.deliveries.size", 0) do
-          post "/user/new",
-               :params => { :user => { :email => email, :email_confirmation => email, :display_name => dup_display_name, :pass_crypt => "testtest", :pass_crypt_confirmation => "testtest" } },
-               :headers => { "HTTP_ACCEPT_LANGUAGE" => locale.to_s }
+          perform_enqueued_jobs do
+            post "/user/new",
+                 :params => { :user => { :email => email, :email_confirmation => email, :display_name => dup_display_name, :pass_crypt => "testtest", :pass_crypt_confirmation => "testtest" } },
+                 :headers => { "HTTP_ACCEPT_LANGUAGE" => locale.to_s }
+          end
         end
       end
       assert_response :success
@@ -75,8 +79,10 @@ class UserCreationTest < ActionDispatch::IntegrationTest
 
       assert_difference("User.count", 0) do
         assert_difference("ActionMailer::Base.deliveries.size", 0) do
-          post "/user/new",
-               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :pass_crypt => "testtest", :pass_crypt_confirmation => "testtest" } }
+          perform_enqueued_jobs do
+            post "/user/new",
+                 :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :pass_crypt => "testtest", :pass_crypt_confirmation => "testtest" } }
+          end
         end
       end
 
@@ -84,9 +90,11 @@ class UserCreationTest < ActionDispatch::IntegrationTest
 
       assert_difference("User.count") do
         assert_difference("ActionMailer::Base.deliveries.size", 1) do
-          post "/user/save",
-               :headers => { "HTTP_ACCEPT_LANGUAGE" => locale.to_s }
-          follow_redirect!
+          perform_enqueued_jobs do
+            post "/user/save",
+                 :headers => { "HTTP_ACCEPT_LANGUAGE" => locale.to_s }
+            follow_redirect!
+          end
         end
       end
 
@@ -122,12 +130,14 @@ class UserCreationTest < ActionDispatch::IntegrationTest
     referer = "/traces/mine"
     assert_difference("User.count") do
       assert_difference("ActionMailer::Base.deliveries.size", 1) do
-        post "/user/new",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :pass_crypt => password, :pass_crypt_confirmation => password }, :referer => referer }
-        assert_redirected_to "/user/terms"
-        post "/user/save",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :pass_crypt => password, :pass_crypt_confirmation => password } }
-        follow_redirect!
+        perform_enqueued_jobs do
+          post "/user/new",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :pass_crypt => password, :pass_crypt_confirmation => password }, :referer => referer }
+          assert_redirected_to "/user/terms"
+          post "/user/save",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :pass_crypt => password, :pass_crypt_confirmation => password } }
+          follow_redirect!
+        end
       end
     end
 
@@ -168,20 +178,22 @@ class UserCreationTest < ActionDispatch::IntegrationTest
     password = "testtest"
     assert_difference("User.count") do
       assert_difference("ActionMailer::Base.deliveries.size", 1) do
-        post "/user/new",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "openid", :auth_uid => "http://localhost:1123/new.tester", :pass_crypt => "", :pass_crypt_confirmation => "" } }
-        assert_response :redirect
-        assert_redirected_to auth_path(:provider => "openid", :openid_url => "http://localhost:1123/new.tester", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_success_path(:provider => "openid", :openid_url => "http://localhost:1123/new.tester", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to "/user/terms"
-        post "/user/save",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "openid", :auth_uid => "http://localhost:1123/new.tester", :pass_crypt => password, :pass_crypt_confirmation => password } }
-        assert_response :redirect
-        follow_redirect!
+        perform_enqueued_jobs do
+          post "/user/new",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "openid", :auth_uid => "http://localhost:1123/new.tester", :pass_crypt => "", :pass_crypt_confirmation => "" } }
+          assert_response :redirect
+          assert_redirected_to auth_path(:provider => "openid", :openid_url => "http://localhost:1123/new.tester", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_success_path(:provider => "openid", :openid_url => "http://localhost:1123/new.tester", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to "/user/terms"
+          post "/user/save",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "openid", :auth_uid => "http://localhost:1123/new.tester", :pass_crypt => password, :pass_crypt_confirmation => password } }
+          assert_response :redirect
+          follow_redirect!
+        end
       end
     end
 
@@ -199,21 +211,23 @@ class UserCreationTest < ActionDispatch::IntegrationTest
     display_name = "new_tester-openid2"
     assert_difference("User.count", 0) do
       assert_difference("ActionMailer::Base.deliveries.size", 0) do
-        post "/user/new",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "openid", :auth_uid => "http://localhost:1123/new.tester", :pass_crypt => "", :pass_crypt_confirmation => "" } }
-        assert_response :redirect
-        assert_redirected_to auth_path(:provider => "openid", :openid_url => "http://localhost:1123/new.tester", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_success_path(:provider => "openid", :openid_url => "http://localhost:1123/new.tester", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_failure_path(:strategy => "openid", :message => "connection_failed", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        follow_redirect!
-        assert_response :success
-        assert_template "users/new"
+        perform_enqueued_jobs do
+          post "/user/new",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "openid", :auth_uid => "http://localhost:1123/new.tester", :pass_crypt => "", :pass_crypt_confirmation => "" } }
+          assert_response :redirect
+          assert_redirected_to auth_path(:provider => "openid", :openid_url => "http://localhost:1123/new.tester", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_success_path(:provider => "openid", :openid_url => "http://localhost:1123/new.tester", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_failure_path(:strategy => "openid", :message => "connection_failed", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          follow_redirect!
+          assert_response :success
+          assert_template "users/new"
+        end
       end
     end
 
@@ -229,19 +243,21 @@ class UserCreationTest < ActionDispatch::IntegrationTest
     referer = "/traces/mine"
     assert_difference("User.count") do
       assert_difference("ActionMailer::Base.deliveries.size", 1) do
-        post "/user/new",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "openid", :auth_uid => "http://localhost:1123/new.tester", :pass_crypt => "", :pass_crypt_confirmation => "" }, :referer => referer }
-        assert_response :redirect
-        assert_redirected_to auth_path(:provider => "openid", :openid_url => "http://localhost:1123/new.tester", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_success_path(:provider => "openid", :openid_url => "http://localhost:1123/new.tester", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to "/user/terms"
-        post "/user/save",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "openid", :auth_uid => "http://localhost:1123/new.tester", :pass_crypt => "testtest", :pass_crypt_confirmation => "testtest" } }
-        follow_redirect!
+        perform_enqueued_jobs do
+          post "/user/new",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "openid", :auth_uid => "http://localhost:1123/new.tester", :pass_crypt => "", :pass_crypt_confirmation => "" }, :referer => referer }
+          assert_response :redirect
+          assert_redirected_to auth_path(:provider => "openid", :openid_url => "http://localhost:1123/new.tester", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_success_path(:provider => "openid", :openid_url => "http://localhost:1123/new.tester", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to "/user/terms"
+          post "/user/save",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "openid", :auth_uid => "http://localhost:1123/new.tester", :pass_crypt => "testtest", :pass_crypt_confirmation => "testtest" } }
+          follow_redirect!
+        end
       end
     end
 
@@ -284,20 +300,22 @@ class UserCreationTest < ActionDispatch::IntegrationTest
     password = "testtest"
     assert_difference("User.count") do
       assert_difference("ActionMailer::Base.deliveries.size", 1) do
-        post "/user/new",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "google", :pass_crypt => "", :pass_crypt_confirmation => "" } }
-        assert_response :redirect
-        assert_redirected_to auth_path(:provider => "google", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_success_path(:provider => "google")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to "/user/terms"
-        post "/user/save",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "google", :auth_uid => "123454321", :pass_crypt => password, :pass_crypt_confirmation => password } }
-        assert_response :redirect
-        follow_redirect!
+        perform_enqueued_jobs do
+          post "/user/new",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "google", :pass_crypt => "", :pass_crypt_confirmation => "" } }
+          assert_response :redirect
+          assert_redirected_to auth_path(:provider => "google", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_success_path(:provider => "google")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to "/user/terms"
+          post "/user/save",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "google", :auth_uid => "123454321", :pass_crypt => password, :pass_crypt_confirmation => password } }
+          assert_response :redirect
+          follow_redirect!
+        end
       end
     end
 
@@ -315,21 +333,23 @@ class UserCreationTest < ActionDispatch::IntegrationTest
     display_name = "new_tester-google2"
     assert_difference("User.count", 0) do
       assert_difference("ActionMailer::Base.deliveries.size", 0) do
-        post "/user/new",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "google", :pass_crypt => "", :pass_crypt_confirmation => "" } }
-        assert_response :redirect
-        assert_redirected_to auth_path(:provider => "google", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_success_path(:provider => "google")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_failure_path(:strategy => "google", :message => "connection_failed", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        follow_redirect!
-        assert_response :success
-        assert_template "users/new"
+        perform_enqueued_jobs do
+          post "/user/new",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "google", :pass_crypt => "", :pass_crypt_confirmation => "" } }
+          assert_response :redirect
+          assert_redirected_to auth_path(:provider => "google", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_success_path(:provider => "google")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_failure_path(:strategy => "google", :message => "connection_failed", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          follow_redirect!
+          assert_response :success
+          assert_template "users/new"
+        end
       end
     end
 
@@ -347,19 +367,21 @@ class UserCreationTest < ActionDispatch::IntegrationTest
     referer = "/traces/mine"
     assert_difference("User.count") do
       assert_difference("ActionMailer::Base.deliveries.size", 1) do
-        post "/user/new",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "google", :pass_crypt => "", :pass_crypt_confirmation => "" }, :referer => referer }
-        assert_response :redirect
-        assert_redirected_to auth_path(:provider => "google", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_success_path(:provider => "google")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to "/user/terms"
-        post "/user/save",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "google", :auth_uid => "http://localhost:1123/new.tester", :pass_crypt => "testtest", :pass_crypt_confirmation => "testtest" } }
-        follow_redirect!
+        perform_enqueued_jobs do
+          post "/user/new",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "google", :pass_crypt => "", :pass_crypt_confirmation => "" }, :referer => referer }
+          assert_response :redirect
+          assert_redirected_to auth_path(:provider => "google", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_success_path(:provider => "google")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to "/user/terms"
+          post "/user/save",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "google", :auth_uid => "http://localhost:1123/new.tester", :pass_crypt => "testtest", :pass_crypt_confirmation => "testtest" } }
+          follow_redirect!
+        end
       end
     end
 
@@ -400,20 +422,22 @@ class UserCreationTest < ActionDispatch::IntegrationTest
     password = "testtest"
     assert_difference("User.count") do
       assert_difference("ActionMailer::Base.deliveries.size", 1) do
-        post "/user/new",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "facebook", :pass_crypt => "", :pass_crypt_confirmation => "" } }
-        assert_response :redirect
-        assert_redirected_to auth_path(:provider => "facebook", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_success_path(:provider => "facebook")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to "/user/terms"
-        post "/user/save",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "facebook", :auth_uid => "123454321", :pass_crypt => password, :pass_crypt_confirmation => password } }
-        assert_response :redirect
-        follow_redirect!
+        perform_enqueued_jobs do
+          post "/user/new",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "facebook", :pass_crypt => "", :pass_crypt_confirmation => "" } }
+          assert_response :redirect
+          assert_redirected_to auth_path(:provider => "facebook", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_success_path(:provider => "facebook")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to "/user/terms"
+          post "/user/save",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "facebook", :auth_uid => "123454321", :pass_crypt => password, :pass_crypt_confirmation => password } }
+          assert_response :redirect
+          follow_redirect!
+        end
       end
     end
 
@@ -431,21 +455,23 @@ class UserCreationTest < ActionDispatch::IntegrationTest
     display_name = "new_tester-facebook2"
     assert_difference("User.count", 0) do
       assert_difference("ActionMailer::Base.deliveries.size", 0) do
-        post "/user/new",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "facebook", :pass_crypt => "", :pass_crypt_confirmation => "" } }
-        assert_response :redirect
-        assert_redirected_to auth_path(:provider => "facebook", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_success_path(:provider => "facebook")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_failure_path(:strategy => "facebook", :message => "connection_failed", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        follow_redirect!
-        assert_response :success
-        assert_template "users/new"
+        perform_enqueued_jobs do
+          post "/user/new",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "facebook", :pass_crypt => "", :pass_crypt_confirmation => "" } }
+          assert_response :redirect
+          assert_redirected_to auth_path(:provider => "facebook", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_success_path(:provider => "facebook")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_failure_path(:strategy => "facebook", :message => "connection_failed", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          follow_redirect!
+          assert_response :success
+          assert_template "users/new"
+        end
       end
     end
 
@@ -461,19 +487,21 @@ class UserCreationTest < ActionDispatch::IntegrationTest
     referer = "/traces/mine"
     assert_difference("User.count") do
       assert_difference("ActionMailer::Base.deliveries.size", 1) do
-        post "/user/new",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "facebook", :pass_crypt => "", :pass_crypt_confirmation => "" }, :referer => referer }
-        assert_response :redirect
-        assert_redirected_to auth_path(:provider => "facebook", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_success_path(:provider => "facebook")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to "/user/terms"
-        post "/user/save",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "facebook", :auth_uid => "http://localhost:1123/new.tester", :pass_crypt => "testtest", :pass_crypt_confirmation => "testtest" } }
-        follow_redirect!
+        perform_enqueued_jobs do
+          post "/user/new",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "facebook", :pass_crypt => "", :pass_crypt_confirmation => "" }, :referer => referer }
+          assert_response :redirect
+          assert_redirected_to auth_path(:provider => "facebook", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_success_path(:provider => "facebook")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to "/user/terms"
+          post "/user/save",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "facebook", :auth_uid => "http://localhost:1123/new.tester", :pass_crypt => "testtest", :pass_crypt_confirmation => "testtest" } }
+          follow_redirect!
+        end
       end
     end
 
@@ -514,20 +542,22 @@ class UserCreationTest < ActionDispatch::IntegrationTest
     password = "testtest"
     assert_difference("User.count") do
       assert_difference("ActionMailer::Base.deliveries.size", 1) do
-        post "/user/new",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "windowslive", :pass_crypt => "", :pass_crypt_confirmation => "" } }
-        assert_response :redirect
-        assert_redirected_to auth_path(:provider => "windowslive", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_success_path(:provider => "windowslive")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to "/user/terms"
-        post "/user/save",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "windowslive", :auth_uid => "123454321", :pass_crypt => password, :pass_crypt_confirmation => password } }
-        assert_response :redirect
-        follow_redirect!
+        perform_enqueued_jobs do
+          post "/user/new",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "windowslive", :pass_crypt => "", :pass_crypt_confirmation => "" } }
+          assert_response :redirect
+          assert_redirected_to auth_path(:provider => "windowslive", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_success_path(:provider => "windowslive")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to "/user/terms"
+          post "/user/save",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "windowslive", :auth_uid => "123454321", :pass_crypt => password, :pass_crypt_confirmation => password } }
+          assert_response :redirect
+          follow_redirect!
+        end
       end
     end
 
@@ -545,21 +575,23 @@ class UserCreationTest < ActionDispatch::IntegrationTest
     display_name = "new_tester-windowslive2"
     assert_difference("User.count", 0) do
       assert_difference("ActionMailer::Base.deliveries.size", 0) do
-        post "/user/new",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "windowslive", :pass_crypt => "", :pass_crypt_confirmation => "" } }
-        assert_response :redirect
-        assert_redirected_to auth_path(:provider => "windowslive", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_success_path(:provider => "windowslive")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_failure_path(:strategy => "windowslive", :message => "connection_failed", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        follow_redirect!
-        assert_response :success
-        assert_template "users/new"
+        perform_enqueued_jobs do
+          post "/user/new",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "windowslive", :pass_crypt => "", :pass_crypt_confirmation => "" } }
+          assert_response :redirect
+          assert_redirected_to auth_path(:provider => "windowslive", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_success_path(:provider => "windowslive")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_failure_path(:strategy => "windowslive", :message => "connection_failed", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          follow_redirect!
+          assert_response :success
+          assert_template "users/new"
+        end
       end
     end
 
@@ -575,19 +607,21 @@ class UserCreationTest < ActionDispatch::IntegrationTest
     referer = "/traces/mine"
     assert_difference("User.count") do
       assert_difference("ActionMailer::Base.deliveries.size", 1) do
-        post "/user/new",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "windowslive", :pass_crypt => "", :pass_crypt_confirmation => "" }, :referer => referer }
-        assert_response :redirect
-        assert_redirected_to auth_path(:provider => "windowslive", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_success_path(:provider => "windowslive")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to "/user/terms"
-        post "/user/save",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "windowslive", :auth_uid => "http://localhost:1123/new.tester", :pass_crypt => "testtest", :pass_crypt_confirmation => "testtest" } }
-        follow_redirect!
+        perform_enqueued_jobs do
+          post "/user/new",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "windowslive", :pass_crypt => "", :pass_crypt_confirmation => "" }, :referer => referer }
+          assert_response :redirect
+          assert_redirected_to auth_path(:provider => "windowslive", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_success_path(:provider => "windowslive")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to "/user/terms"
+          post "/user/save",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "windowslive", :auth_uid => "http://localhost:1123/new.tester", :pass_crypt => "testtest", :pass_crypt_confirmation => "testtest" } }
+          follow_redirect!
+        end
       end
     end
 
@@ -628,20 +662,22 @@ class UserCreationTest < ActionDispatch::IntegrationTest
     password = "testtest"
     assert_difference("User.count") do
       assert_difference("ActionMailer::Base.deliveries.size", 1) do
-        post "/user/new",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "github", :pass_crypt => "", :pass_crypt_confirmation => "" } }
-        assert_response :redirect
-        assert_redirected_to auth_path(:provider => "github", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_success_path(:provider => "github")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to "/user/terms"
-        post "/user/save",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "github", :auth_uid => "123454321", :pass_crypt => password, :pass_crypt_confirmation => password } }
-        assert_response :redirect
-        follow_redirect!
+        perform_enqueued_jobs do
+          post "/user/new",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "github", :pass_crypt => "", :pass_crypt_confirmation => "" } }
+          assert_response :redirect
+          assert_redirected_to auth_path(:provider => "github", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_success_path(:provider => "github")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to "/user/terms"
+          post "/user/save",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "github", :auth_uid => "123454321", :pass_crypt => password, :pass_crypt_confirmation => password } }
+          assert_response :redirect
+          follow_redirect!
+        end
       end
     end
 
@@ -659,21 +695,23 @@ class UserCreationTest < ActionDispatch::IntegrationTest
     display_name = "new_tester-github2"
     assert_difference("User.count", 0) do
       assert_difference("ActionMailer::Base.deliveries.size", 0) do
-        post "/user/new",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "github", :pass_crypt => "", :pass_crypt_confirmation => "" } }
-        assert_response :redirect
-        assert_redirected_to auth_path(:provider => "github", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_success_path(:provider => "github")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_failure_path(:strategy => "github", :message => "connection_failed", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        follow_redirect!
-        assert_response :success
-        assert_template "users/new"
+        perform_enqueued_jobs do
+          post "/user/new",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "github", :pass_crypt => "", :pass_crypt_confirmation => "" } }
+          assert_response :redirect
+          assert_redirected_to auth_path(:provider => "github", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_success_path(:provider => "github")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_failure_path(:strategy => "github", :message => "connection_failed", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          follow_redirect!
+          assert_response :success
+          assert_template "users/new"
+        end
       end
     end
 
@@ -689,19 +727,21 @@ class UserCreationTest < ActionDispatch::IntegrationTest
     referer = "/traces/mine"
     assert_difference("User.count") do
       assert_difference("ActionMailer::Base.deliveries.size", 1) do
-        post "/user/new",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "github", :pass_crypt => "", :pass_crypt_confirmation => "" }, :referer => referer }
-        assert_response :redirect
-        assert_redirected_to auth_path(:provider => "github", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_success_path(:provider => "github")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to "/user/terms"
-        post "/user/save",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "github", :auth_uid => "http://localhost:1123/new.tester", :pass_crypt => "testtest", :pass_crypt_confirmation => "testtest" } }
-        follow_redirect!
+        perform_enqueued_jobs do
+          post "/user/new",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "github", :pass_crypt => "", :pass_crypt_confirmation => "" }, :referer => referer }
+          assert_response :redirect
+          assert_redirected_to auth_path(:provider => "github", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_success_path(:provider => "github")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to "/user/terms"
+          post "/user/save",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "github", :auth_uid => "http://localhost:1123/new.tester", :pass_crypt => "testtest", :pass_crypt_confirmation => "testtest" } }
+          follow_redirect!
+        end
       end
     end
 
@@ -742,20 +782,22 @@ class UserCreationTest < ActionDispatch::IntegrationTest
     password = "testtest"
     assert_difference("User.count") do
       assert_difference("ActionMailer::Base.deliveries.size", 1) do
-        post "/user/new",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "wikipedia", :pass_crypt => "", :pass_crypt_confirmation => "" } }
-        assert_response :redirect
-        assert_redirected_to auth_path(:provider => "wikipedia", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_success_path(:provider => "wikipedia", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to "/user/terms"
-        post "/user/save",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "wikipedia", :auth_uid => "123454321", :pass_crypt => password, :pass_crypt_confirmation => password } }
-        assert_response :redirect
-        follow_redirect!
+        perform_enqueued_jobs do
+          post "/user/new",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "wikipedia", :pass_crypt => "", :pass_crypt_confirmation => "" } }
+          assert_response :redirect
+          assert_redirected_to auth_path(:provider => "wikipedia", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_success_path(:provider => "wikipedia", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to "/user/terms"
+          post "/user/save",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "wikipedia", :auth_uid => "123454321", :pass_crypt => password, :pass_crypt_confirmation => password } }
+          assert_response :redirect
+          follow_redirect!
+        end
       end
     end
 
@@ -773,21 +815,23 @@ class UserCreationTest < ActionDispatch::IntegrationTest
     display_name = "new_tester-wikipedia2"
     assert_difference("User.count", 0) do
       assert_difference("ActionMailer::Base.deliveries.size", 0) do
-        post "/user/new",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "wikipedia", :pass_crypt => "", :pass_crypt_confirmation => "" } }
-        assert_response :redirect
-        assert_redirected_to auth_path(:provider => "wikipedia", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_success_path(:provider => "wikipedia", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_failure_path(:strategy => "wikipedia", :message => "connection_failed", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        follow_redirect!
-        assert_response :success
-        assert_template "users/new"
+        perform_enqueued_jobs do
+          post "/user/new",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "wikipedia", :pass_crypt => "", :pass_crypt_confirmation => "" } }
+          assert_response :redirect
+          assert_redirected_to auth_path(:provider => "wikipedia", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_success_path(:provider => "wikipedia", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_failure_path(:strategy => "wikipedia", :message => "connection_failed", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          follow_redirect!
+          assert_response :success
+          assert_template "users/new"
+        end
       end
     end
 
@@ -803,19 +847,21 @@ class UserCreationTest < ActionDispatch::IntegrationTest
     referer = "/traces/mine"
     assert_difference("User.count") do
       assert_difference("ActionMailer::Base.deliveries.size", 1) do
-        post "/user/new",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "wikipedia", :pass_crypt => "", :pass_crypt_confirmation => "" }, :referer => referer }
-        assert_response :redirect
-        assert_redirected_to auth_path(:provider => "wikipedia", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to auth_success_path(:provider => "wikipedia", :origin => "/user/new")
-        follow_redirect!
-        assert_response :redirect
-        assert_redirected_to "/user/terms"
-        post "/user/save",
-             :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "wikipedia", :auth_uid => "http://localhost:1123/new.tester", :pass_crypt => "testtest", :pass_crypt_confirmation => "testtest" } }
-        follow_redirect!
+        perform_enqueued_jobs do
+          post "/user/new",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "wikipedia", :pass_crypt => "", :pass_crypt_confirmation => "" }, :referer => referer }
+          assert_response :redirect
+          assert_redirected_to auth_path(:provider => "wikipedia", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to auth_success_path(:provider => "wikipedia", :origin => "/user/new")
+          follow_redirect!
+          assert_response :redirect
+          assert_redirected_to "/user/terms"
+          post "/user/save",
+               :params => { :user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :auth_provider => "wikipedia", :auth_uid => "http://localhost:1123/new.tester", :pass_crypt => "testtest", :pass_crypt_confirmation => "testtest" } }
+          follow_redirect!
+        end
       end
     end
 
index e6d0c0abdcdaa99e2a3112c4ca6b0a7c0c30952d..6b76d82a49fe623fe4516bd23e5ce9616d4ffa45 100644 (file)
@@ -207,4 +207,29 @@ class RelationTest < ActiveSupport::TestCase
     assert_equal 39, changeset.min_lat
     assert_equal 39, changeset.max_lat
   end
+
+  def test_changeset_bbox_delete_relation
+    orig_relation = create(:relation)
+    node1 = create(:node, :longitude => 116, :latitude => 39)
+    node2 = create(:node, :longitude => 39, :latitude => 116)
+    create(:relation_member, :relation => orig_relation, :member_type => "Node", :member_id => node1.id)
+    create(:relation_member, :relation => orig_relation, :member_type => "Node", :member_id => node2.id)
+    user = create(:user)
+    changeset = create(:changeset, :user => user)
+    assert_nil changeset.min_lon
+    assert_nil changeset.max_lon
+    assert_nil changeset.max_lat
+    assert_nil changeset.min_lat
+
+    new_relation = Relation.new
+    new_relation.id = orig_relation.id
+    new_relation.version = orig_relation.version
+    new_relation.changeset_id = changeset.id
+    orig_relation.delete_with_history!(new_relation, user)
+    changeset.reload
+    assert_equal 39, changeset.min_lon
+    assert_equal 116, changeset.max_lon
+    assert_equal 39, changeset.min_lat
+    assert_equal 116, changeset.max_lat
+  end
 end
index 83cf909dd94f208c5b89c20e024f8e6941e040f4..fca1f64c958adf887b42c53b491fab454447a56e 100644 (file)
@@ -11,6 +11,7 @@ WebMock.disable_net_connect!(:allow_localhost => true)
 module ActiveSupport
   class TestCase
     include FactoryBot::Syntax::Methods
+    include ActiveJob::TestHelper
 
     ##
     # takes a block which is executed in the context of a different