]> git.openstreetmap.org Git - rails.git/commitdiff
Merge branch 'master' into next
authorTom Hughes <tom@compton.nu>
Sun, 10 Jun 2018 16:02:12 +0000 (17:02 +0100)
committerTom Hughes <tom@compton.nu>
Sun, 10 Jun 2018 16:02:12 +0000 (17:02 +0100)
19 files changed:
1  2 
.rubocop_todo.yml
Gemfile
Gemfile.lock
app/assets/stylesheets/common.scss
app/models/user.rb
app/views/browse/note.html.erb
app/views/diary_entry/_diary_comment.html.erb
app/views/diary_entry/_diary_entry.html.erb
app/views/layouts/_header.html.erb
app/views/user/view.html.erb
config/locales/en.yml
config/routes.rb
test/models/issue_test.rb
test/models/report_test.rb
test/system/issues_test.rb
test/system/report_diary_comment_test.rb
test/system/report_diary_entry_test.rb
test/system/report_note_test.rb
test/system/report_user_test.rb

diff --combined .rubocop_todo.yml
index 5846de44f47d987a1bf16d6f67a19dd7227617e2,362cfcb3235123751c8018c9fb69250bff842c42..da801d681ab11b8071dcf50a836d3b884cb36ccd
@@@ -33,9 -33,9 +33,9 @@@ Lint/AssignmentInCondition
      - 'app/controllers/application_controller.rb'
      - 'app/controllers/geocoder_controller.rb'
      - 'app/controllers/notes_controller.rb'
-     - 'app/controllers/trace_controller.rb'
+     - 'app/controllers/traces_controller.rb'
      - 'app/controllers/user_controller.rb'
-     - 'app/controllers/user_preference_controller.rb'
+     - 'app/controllers/user_preferences_controller.rb'
      - 'app/helpers/application_helper.rb'
      - 'app/helpers/browse_helper.rb'
      - 'app/models/client_application.rb'
@@@ -67,7 -67,7 +67,7 @@@ Metrics/AbcSize
  # Offense count: 41
  # Configuration parameters: CountComments, ExcludedMethods.
  Metrics/BlockLength:
-   Max: 250
 -  Max: 247
++  Max: 257
  
  # Offense count: 12
  # Configuration parameters: CountBlocks.
diff --combined Gemfile
index a9a6cb4b6d1466d65c41c05d8037a695e8900b54,7d59cceb1d14338cd1aa45a32e21bcadd722ae8b..ef14d06c5b86eaed0853550541b81cfa01c8198d
+++ b/Gemfile
@@@ -70,9 -70,6 +70,9 @@@ gem "omniauth-windowslive
  # Markdown formatting support
  gem "redcarpet"
  
 +# For status transitions of Issues
 +gem "aasm"
 +
  # Load libxml support for XML parsing and generation
  gem "libxml-ruby", ">= 2.0.5", :require => "libxml"
  
@@@ -108,6 -105,8 +108,8 @@@ gem "logstasher
  # Gems useful for development
  group :development do
    gem "annotate"
+   gem "better_errors"
+   gem "binding_of_caller"
    gem "listen"
    gem "vendorer"
  end
diff --combined Gemfile.lock
index d1a9a0dd2ffb18f048cb34537d3377f10147a20d,8634f8df8eb256ae8cd95bd12a260a66808211f0..49f9b5977231da55204cf6ac91542989ba31538b
@@@ -2,7 -2,6 +2,7 @@@ GE
    remote: https://rubygems.org/
    specs:
      SystemTimer (1.2.3)
 +    aasm (4.1.0)
      actioncable (5.1.5)
        actionpack (= 5.1.5)
        nio4r (~> 2.0)
        tzinfo (~> 1.1)
      addressable (2.5.2)
        public_suffix (>= 2.0.2, < 4.0)
-     annotate (2.7.2)
+     annotate (2.7.3)
        activerecord (>= 3.2, < 6.0)
        rake (>= 10.4, < 13.0)
      arel (8.0.0)
      ast (2.4.0)
-     autoprefixer-rails (8.2.0)
+     autoprefixer-rails (8.5.1)
        execjs
+     better_errors (2.4.0)
+       coderay (>= 1.0.0)
+       erubi (>= 1.0.0)
+       rack (>= 0.9.0)
      bigdecimal (1.1.0)
+     binding_of_caller (0.8.0)
+       debug_inspector (>= 0.0.1)
      builder (3.2.3)
-     canonical-rails (0.2.2)
-       rails (>= 4.1, < 5.2)
+     canonical-rails (0.2.3)
+       rails (>= 4.1, < 5.3)
      capybara (2.18.0)
        addressable
        mini_mime (>= 0.1.3)
@@@ -64,6 -69,7 +70,7 @@@
        xpath (>= 2.0, < 4.0)
      climate_control (0.2.0)
      cliver (0.3.2)
+     coderay (1.1.2)
      coffee-rails (4.2.2)
        coffee-script (>= 2.2.0)
        railties (>= 4.0.0)
        tins (~> 1.6)
      crack (0.4.3)
        safe_yaml (~> 1.0.0)
-     crass (1.0.3)
-     dalli (2.7.6)
+     crass (1.0.4)
+     dalli (2.7.8)
+     debug_inspector (0.0.3)
      docile (1.1.5)
      dynamic_form (1.1.4)
      erubi (1.7.1)
      execjs (2.7.0)
-     exifr (1.3.3)
-     factory_bot (4.8.2)
+     exifr (1.3.4)
+     factory_bot (4.10.0)
        activesupport (>= 3.0.0)
-     factory_bot_rails (4.8.2)
-       factory_bot (~> 4.8.2)
+     factory_bot_rails (4.10.0)
+       factory_bot (~> 4.10.0)
        railties (>= 3.0.0)
      faraday (0.12.2)
        multipart-post (>= 1.2, < 3)
        sprockets
      image_size (1.5.0)
      in_threads (1.5.0)
-     jquery-rails (4.3.1)
+     jquery-rails (4.3.3)
        rails-dom-testing (>= 1, < 3)
        railties (>= 4.2.0)
        thor (>= 0.14, < 2.0)
      multi_json (1.13.1)
      multi_xml (0.6.0)
      multipart-post (2.0.0)
-     nio4r (2.3.0)
+     nio4r (2.3.1)
      nokogiri (1.8.2)
        mini_portile2 (~> 2.3.0)
      nokogumbo (1.5.0)
      omniauth (1.8.1)
        hashie (>= 3.4.6, < 3.6.0)
        rack (>= 1.6.2, < 3)
-     omniauth-facebook (4.0.0)
+     omniauth-facebook (5.0.0)
        omniauth-oauth2 (~> 1.2)
      omniauth-github (1.3.0)
        omniauth (~> 1.5)
        mimemagic (~> 0.3.0)
        terrapin (~> 0.6.0)
      parallel (1.12.1)
-     parser (2.5.0.5)
+     parser (2.5.1.0)
        ast (~> 2.4.0)
      pg (0.21.0)
-     poltergeist (1.17.0)
-       capybara (~> 2.1)
+     poltergeist (1.18.1)
+       capybara (>= 2.1, < 4)
        cliver (~> 0.3.1)
        websocket-driver (>= 0.2.0)
      powerpack (0.1.1)
      progress (3.4.0)
      psych (3.0.2)
      public_suffix (3.0.2)
-     puma (3.11.3)
+     puma (3.11.4)
      r2 (0.2.7)
-     rack (2.0.4)
+     rack (2.0.5)
      rack-cors (1.0.2)
      rack-openid (1.3.1)
        rack (>= 1.1.0)
        ruby-openid (>= 2.1.8)
-     rack-test (0.8.3)
+     rack-test (1.0.0)
        rack (>= 1.0, < 3)
      rack-uri_sanitizer (0.0.2)
      rails (5.1.5)
        rack (>= 1.4)
      rinku (2.0.4)
      rotp (3.3.1)
-     rubocop (0.54.0)
+     rubocop (0.56.0)
        parallel (~> 1.10)
        parser (>= 2.5)
        powerpack (~> 0.1)
      ruby-progressbar (1.9.0)
      ruby_dep (1.5.0)
      safe_yaml (1.0.4)
-     sanitize (4.6.4)
+     sanitize (4.6.5)
        crass (~> 1.0.2)
        nokogiri (>= 1.4.4)
        nokogumbo (~> 1.4)
        sprockets (>= 2.8, < 4.0)
        sprockets-rails (>= 2.0, < 4.0)
        tilt (>= 1.1, < 3)
-     secure_headers (5.0.5)
-       useragent (>= 0.15.0)
+     secure_headers (6.0.0)
      simplecov (0.14.1)
        docile (~> 1.1.0)
        json (>= 1.8, < 3)
      tins (1.16.3)
      tzinfo (1.2.5)
        thread_safe (~> 0.1)
-     uglifier (4.1.8)
+     uglifier (4.1.10)
        execjs (>= 0.3.0, < 3)
-     unicode-display_width (1.3.0)
-     useragent (0.16.10)
+     unicode-display_width (1.3.2)
      validates_email_format_of (1.6.3)
        i18n
      vendorer (0.1.16)
-     webmock (3.3.0)
+     webmock (3.4.1)
        addressable (>= 2.3.6)
        crack (>= 0.3.2)
        hashdiff
      websocket-driver (0.6.5)
        websocket-extensions (>= 0.1.0)
      websocket-extensions (0.1.3)
-     xpath (3.0.0)
+     xpath (3.1.0)
        nokogiri (~> 1.8)
  
  PLATFORMS
  
  DEPENDENCIES
    SystemTimer (>= 1.1.3)
 +  aasm
    actionpack-page_caching
    annotate
    autoprefixer-rails
+   better_errors
    bigdecimal (~> 1.1.0)
+   binding_of_caller
    canonical-rails
    capybara (~> 2.13)
    coffee-rails (~> 4.2)
    webmock
  
  BUNDLED WITH
-    1.15.4
+    1.16.2
index 50b38e7a358e368257f8cb862554791eb708b110,cef2efbb2d139326a70addbf41395a97c7943194..f9214b24dba1a94dd84c129541bfefbd6e09cd7b
@@@ -1028,7 -1028,7 +1028,7 @@@ header .search_forms
  
  /* Rules for search sidebar */
  
- .search_results_entry {
#sidebar .search_results_entry {
    ul li {
      border-bottom: $keyline;
      cursor: pointer;
      &.selected { background: $list-highlight; }
    }
  
-   .search_details {
-     display: block;
-     float: right;
-     text-align: right;
-     margin-top: 0.2em;
-     margin-left: 0.5em;
+   .search_more .loader {
+     display: none;
+     width: 100%;
    }
  }
  
@@@ -1131,6 -1128,11 +1128,11 @@@ tr.turn:hover 
    .comments-0 {
      opacity: 0.5;
    }
+   .changeset_more .loader {
+     display: none;
+     width: 100%;
+   }
  }
  
  /* Rules for the browse sidebar */
    }
  }
  
- .content-heading .hide_unless_logged_in { // hacky selector, better to just add a new class to this div
-   display: inline;
- }
  .pagination {
    padding-top: $lineheight;
  }
    display: none;
  }
  
- .message-read .message-buttons {
+ .messages-show .message-buttons {
    margin-top: $lineheight;
    margin-bottom: $lineheight * 1.5;
    padding-top: $lineheight;
    border-top: 1px solid $lightgrey;
  }
  
- .message-read .buttons .mark-unread-button {
+ .messages-show .buttons .mark-unread-button {
    border-radius: 0;
  }
  
@@@ -2822,59 -2820,3 +2820,59 @@@ input.richtext_title[type="text"] 
      display: none;
    }
  }
 +
 +.read-reports {
 +  background: #eee;
 +  opacity: 0.7;
 +}
 +
 +.report-related-block {
 +  display:inline-block;
 +}
 +
 +.report-block {
 +  width:475px;
 +  float:left;
 +  margin-right:100px;
 +}
 +
 +.related-reports {
 +  width: 280px;
 +  float: right;
 +
 +  ul {
 +    padding-left: $lineheight;
 +    margin-bottom: 0;
 +
 +    li {
 +      list-style: disc;
 +    }
 +  }
 +}
 +
 +.issue-comments {
 +  width:475px;
 +}
 +
 +.issues-list {
 +  td:nth-child(2) {
 +    white-space: nowrap;
 +  }
 +}
 +
 +.report-disclaimer {
 +  background: #fff1f0;
 +  color: #d85030;
 +  border-color: rgba(216, 80, 48, 0.3);
 +  padding: 10px 20px;
 +  margin-bottom: $lineheight;
 +
 +  ul {
 +    padding-left: $lineheight;
 +    margin-bottom: 0;
 +
 +    li {
 +      list-style: disc;
 +    }
 +  }
 +}
diff --combined app/models/user.rb
index 2a0a5ab4508f2c193c048cf3eeb24edff5262fdc,036f2fdc478692bc4f52b17ea8ed8f8aaf42d1f1..aaa00169f5210f2ac5fda89f0e1b8bd5d839811e
@@@ -75,11 -75,6 +75,11 @@@ class User < ActiveRecord::Bas
  
    has_many :roles, :class_name => "UserRole"
  
 +  has_many :issues, :class_name => "Issue", :foreign_key => :reported_user_id
 +  has_many :issue_comments
 +
 +  has_many :reports
 +
    scope :visible, -> { where(:status => %w[pending active confirmed]) }
    scope :active, -> { where(:status => %w[active confirmed]) }
    scope :identifiable, -> { where(:data_public => true) }
    before_save :encrypt_password
    before_save :update_tile
    after_save :spam_check
+   after_save :reset_preferred_languages
  
    def to_param
      display_name
      @preferred_languages ||= Locale.list(languages)
    end
  
+   def reset_preferred_languages
+     @preferred_languages = nil
+   end
    def nearby(radius = NEARBY_RADIUS, num = NEARBY_USERS)
      if home_lon && home_lat
        gc = OSM::GreatCircle.new(home_lat, home_lon)
index fa9e886280780a1cfbefdb4a045b2f84697dba8b,37067c311fe812d3dab1606763094f0cbd8352bc..53ea0759e9f79866bbbfc97dfe416e0b0a1d0e8d
@@@ -1,12 -1,12 +1,12 @@@
- <% set_title(t('browse.note.title', :id => @note.id)) %>
+ <% set_title(t('.title', :id => @note.id)) %>
  
  <h2>
    <a class="geolink" href="<%= root_path %>"><span class="icon close"></span></a>
-   <%= t "browse.note.#{@note.status}_title", :note_name => @note.id %>
+   <%= t ".#{@note.status}_title", :note_name => @note.id %>
  </h2>
  
  <div class="browse-section">
-   <h4><%= t('browse.note.description') %></h4>
+   <h4><%= t('.description') %></h4>
    <div class="note-description">
      <%= h(@note_comments.first.body.to_html) %>
    </div>
      <p class='warning'><%= t "javascripts.notes.show.anonymous_warning" %></p>
    <% end -%>
  
 +  <% if current_user && current_user != @note.author %>
 +    <p class="deemphasize"><%= report_link(t(".report"), @note) %></p>
 +  <% end %>
 +
    <% if @note_comments.length > 1 %>
      <div class='note-comments'>
        <ul>
      <form action="#">
        <textarea class="comment" name="text" cols="40" rows="5"></textarea>
        <div class="buttons clearfix">
-         <input type="submit" name="hide" value="<%= t('javascripts.notes.show.hide') %>" class="hide_unless_moderator deemphasize" data-note-id="<%= @note.id %>" data-method="DELETE" data-url="<%= note_url(@note, 'json') %>">
-         <input type="submit" name="close" value="<%= t('javascripts.notes.show.resolve') %>" class="hide_unless_logged_in" data-note-id="<%= @note.id %>" data-method="POST" data-url="<%= close_note_url(@note, 'json') %>">
+         <% if current_user and current_user.moderator? -%>
+           <input type="submit" name="hide" value="<%= t('javascripts.notes.show.hide') %>" class="deemphasize" data-note-id="<%= @note.id %>" data-method="DELETE" data-url="<%= note_url(@note, 'json') %>">
+         <% end -%>
+         <% if current_user -%>
+           <input type="submit" name="close" value="<%= t('javascripts.notes.show.resolve') %>" data-note-id="<%= @note.id %>" data-method="POST" data-url="<%= close_note_url(@note, 'json') %>">
+         <% end -%>
          <input type="submit" name="comment" value="<%= t('javascripts.notes.show.comment') %>" data-note-id="<%= @note.id %>" data-method="POST" data-url="<%= comment_note_url(@note, 'json') %>" disabled="1">
        </div>
      </form>
      <form action="#">
        <input type="hidden" name="text" value="">
        <div class="buttons clearfix">
-         <input type="submit" name="hide" value="<%= t('javascripts.notes.show.hide') %>" class="hide_unless_moderator deemphasize" data-note-id="<%= @note.id %>" data-method="DELETE" data-url="<%= note_url(@note, 'json') %>">
-         <input type="submit" name="reopen" value="<%= t('javascripts.notes.show.reactivate') %>" class="hide_unless_logged_in" data-note-id="<%= @note.id %>" data-method="POST" data-url="<%= reopen_note_url(@note, 'json') %>">
+         <% if current_user and current_user.moderator? -%>
+           <input type="submit" name="hide" value="<%= t('javascripts.notes.show.hide') %>" class="deemphasize" data-note-id="<%= @note.id %>" data-method="DELETE" data-url="<%= note_url(@note, 'json') %>">
+         <% end -%>
+         <% if current_user -%>
+           <input type="submit" name="reopen" value="<%= t('javascripts.notes.show.reactivate') %>" data-note-id="<%= @note.id %>" data-method="POST" data-url="<%= reopen_note_url(@note, 'json') %>">
+         <% end -%>
        </div>
      </form>
    <% end %>
index 8e17b095422a86c0681511c87fce68c97e5eaa14,8565ecc67e4c4053a7f3790883d0f0c91d3f4cce..4ac9a0f967f1950dbe6e86f98b8a9d2c1f7e5a42
@@@ -1,13 -1,10 +1,15 @@@
  <div class="clearfix diary-comment">
    <%= user_thumbnail diary_comment.user %>
-   <p class="deemphasize comment-heading" id="comment<%= diary_comment.id %>"><%= raw(t('diary_entry.diary_comment.comment_from', :link_user => (link_to h(diary_comment.user.display_name), user_path(diary_comment.user)), :comment_created_at => link_to(l(diary_comment.created_at, :format => :friendly), :anchor => "comment#{diary_comment.id}"))) %>
 -  <p class="deemphasize comment-heading" id="comment<%= diary_comment.id %>"><%= raw(t('.comment_from', :link_user => (link_to h(diary_comment.user.display_name), user_path(diary_comment.user)), :comment_created_at => link_to(l(diary_comment.created_at, :format => :friendly), :anchor => "comment#{diary_comment.id}"))) %></p>
++  <p class="deemphasize comment-heading" id="comment<%= diary_comment.id %>"><%= raw(t('.comment_from', :link_user => (link_to h(diary_comment.user.display_name), user_path(diary_comment.user)), :comment_created_at => link_to(l(diary_comment.created_at, :format => :friendly), :anchor => "comment#{diary_comment.id}"))) %>
 +    <% if current_user and diary_comment.user.id != current_user.id %>
 +      | <%= report_link(t(".report"), diary_comment) %>
 +    <% end %>
 +  </p>
 +
    <div class="richtext"><%= diary_comment.body.to_html %></div>
-   <%= if_administrator(:span) do %>
-     <%= link_to t('diary_entry.diary_comment.hide_link'), hide_diary_comment_path(:display_name => diary_comment.diary_entry.user.display_name, :id => diary_comment.diary_entry.id, :comment => diary_comment.id), :method => :post, :data=> { :confirm => t('diary_entry.diary_comment.confirm') } %>
+   <% if current_user && current_user.administrator? %>
+     <span>
+       <%= link_to t('.hide_link'), hide_diary_comment_path(:display_name => diary_comment.diary_entry.user.display_name, :id => diary_comment.diary_entry.id, :comment => diary_comment.id), :method => :post, :data=> { :confirm => t('.confirm') } %>
+     </span>
    <% end %>
  </div>
index ce311c168f5798ed3c464f558ccc6a2e2e5589dd,848221a2803ac6d0e6fcff71c18dead3ab696334..930f20e5ecd1e48dbe037889e44187c46c0ae97c
@@@ -1,13 -1,13 +1,13 @@@
  <div class='diary_post'>
    <div class='post_heading clearfix'>
-     <% if !@this_user %>
+     <% if !@user %>
        <%= user_thumbnail diary_entry.user %>
      <% end %>
  
      <h2><%= link_to h(diary_entry.title), :action => 'view', :display_name => diary_entry.user.display_name, :id => diary_entry.id %></h2>
  
      <small class='deemphasize'>
-       <%= raw(t 'diary_entry.diary_entry.posted_by', :link_user => (link_to h(diary_entry.user.display_name), user_path(diary_entry.user)), :created => l(diary_entry.created_at, :format => :blog), :language_link => (link_to h(diary_entry.language.name), :controller => 'diary_entry', :action => 'list', :display_name => nil, :language => diary_entry.language_code)) %>
+       <%= raw(t '.posted_by', :link_user => (link_to h(diary_entry.user.display_name), user_path(diary_entry.user)), :created => l(diary_entry.created_at, :format => :blog), :language_link => (link_to h(diary_entry.language.name), :controller => 'diary_entry', :action => 'list', :display_name => nil, :language => diary_entry.language_code)) %>
      </small>
  
    </div>
  
    <ul class='secondary-actions clearfix'>
      <% if params[:action] == 'list' %>
-       <li><%= link_to t('diary_entry.diary_entry.comment_link'), :action => 'view', :display_name => diary_entry.user.display_name, :id => diary_entry.id, :anchor => 'newcomment' %></li>
-       <li><%= link_to t('diary_entry.diary_entry.reply_link'), :controller => 'message', :action => 'new', :display_name => diary_entry.user.display_name, :title => "Re: #{diary_entry.title}" %></li>
-       <li><%= link_to t('diary_entry.diary_entry.comment_count', :count => diary_entry.visible_comments.count), :action => 'view', :display_name => diary_entry.user.display_name, :id => diary_entry.id, :anchor => 'comments' %></li>
+       <li><%= link_to t('.comment_link'), :action => 'view', :display_name => diary_entry.user.display_name, :id => diary_entry.id, :anchor => 'newcomment' %></li>
+       <li><%= link_to t('.reply_link'), new_message_path(diary_entry.user, :message => { :title => "Re: #{diary_entry.title}" }) %></li>
+       <li><%= link_to t('.comment_count', :count => diary_entry.visible_comments.count), :action => 'view', :display_name => diary_entry.user.display_name, :id => diary_entry.id, :anchor => 'comments' %></li>
      <% end %>
  
-     <%= if_user(diary_entry.user, :li) do %>
-       <%= link_to t('diary_entry.diary_entry.edit_link'), :action => 'edit', :display_name => diary_entry.user.display_name, :id => diary_entry.id %>
+     <% if current_user && current_user == diary_entry.user %>
+       <li><%= link_to t('.edit_link'), :action => 'edit', :display_name => diary_entry.user.display_name, :id => diary_entry.id %></li>
      <% end %>
  
-     <%= if_administrator(:li) do %>
-       <%= link_to t('diary_entry.diary_entry.hide_link'), hide_diary_entry_path(:display_name => diary_entry.user.display_name, :id => diary_entry.id), :method => :post, :data => { :confirm => t('diary_entry.diary_entry.confirm') } %>
 +    <% if current_user and diary_entry.user != current_user %>
 +      <li>
 +        <%= report_link(t(".report"), diary_entry) %>
 +      </li>
 +    <% end %>
 +
 -      <li><%= link_to t('.hide_link'), hide_diary_entry_path(:display_name => diary_entry.user.display_name, :id => diary_entry.id), :method => :post, :data => { :confirm => t('.confirm') } %></li>
+     <% if current_user && current_user.administrator? %>
++      <li>
++        <%= link_to t('.hide_link'), hide_diary_entry_path(:display_name => diary_entry.user.display_name, :id => diary_entry.id), :method => :post, :data => { :confirm => t('.confirm') } %>
++      </li>
      <% end %>
    </ul>
  </div>
index d8e5443b1384406b876739000453b0282a8f4606,8411fefdb71a8f5316c6d5b0adad0a9df9ceeea0..c9107e7a83d16111d8308f7cda6c0e5d30b38d66
@@@ -38,9 -38,6 +38,9 @@@
    </nav>
    <nav class='secondary'>
      <ul>
 +      <% if current_user and ( current_user.administrator? or current_user.moderator? ) %>
 +        <li class="compact-hide <%= current_page_class(issues_path) %>"><%= link_to t('layouts.issues'), issues_path %></li>
 +      <% end %>
        <li class="compact-hide <%= current_page_class(traces_path) %>"><%= link_to t('layouts.gps_traces'), traces_path %></li>
        <li class="compact-hide <%= current_page_class(diary_path) %>"><%= link_to t('layouts.user_diaries'), diary_path %></li>
        <li class="compact-hide <%= current_page_class(copyright_path) %>"><%= link_to t('layouts.copyright'), copyright_path %></li>
@@@ -67,7 -64,7 +67,7 @@@
          </a>
          <ul class='dropdown-menu'>
            <li>
-             <%= link_to inbox_path(:display_name => current_user.display_name) do %>
+             <%= link_to inbox_messages_path do %>
                <span class='count-number'><%= number_with_delimiter(current_user.new_messages.size) %></span>
                <%= t('user.view.my messages') %>
              <% end %>
index f797c4ba4e742ffb7bc406782ff38a427c44eeb0,3a09165b9d34ba8eafadfb0a5ddc96becc2352b4..0acb3f0145a622e05207d1bb109c18083064e503
@@@ -1,43 -1,43 +1,43 @@@
  <% content_for :heading do %>
    <div id='userinformation'>
-     <%= user_image @this_user %>
+     <%= user_image @user %>
      <div class='userinformation-inner'>
-       <h1><%= @this_user.display_name %><%= role_icons(@this_user) %></h1>
-       <% if current_user and @this_user.id == current_user.id %>
+       <h1><%= @user.display_name %><%= role_icons(@user) %></h1>
+       <% if current_user and @user.id == current_user.id %>
          <!-- Displaying user's own profile page to themself -->
          <ul class='secondary-actions clearfix'>
            <li>
-             <%= link_to t('user.view.my edits'), :controller => 'changeset', :action => 'list', :display_name => current_user.display_name %>
+             <%= link_to t('.my edits'), :controller => 'changeset', :action => 'list', :display_name => current_user.display_name %>
              <span class='count-number'><%= number_with_delimiter(current_user.changesets.size) %></span>
            </li>
            <li>
-             <%= link_to t('user.view.my notes'), :controller => 'notes', :action=> 'mine' %>
+             <%= link_to t('.my notes'), :controller => 'notes', :action=> 'mine' %>
            </li>
            <li>
-             <%= link_to t('user.view.my traces'), :controller => 'trace', :action=>'mine' %>
+             <%= link_to t('.my traces'), :controller => 'traces', :action => 'mine' %>
              <span class='count-number'><%= number_with_delimiter(current_user.traces.size) %></span>
            </li>
            <li>
-             <%= link_to t('user.view.my diary'), :controller => 'diary_entry', :action => 'list', :display_name => current_user.display_name %>
+             <%= link_to t('.my diary'), :controller => 'diary_entry', :action => 'list', :display_name => current_user.display_name %>
              <span class='count-number'><%= number_with_delimiter(current_user.diary_entries.size) %></span>
            </li>
            <li>
-             <%= link_to t('user.view.my comments' ), :controller => 'diary_entry', :action => 'comments', :display_name => current_user.display_name %>
+             <%= link_to t('.my comments' ), :controller => 'diary_entry', :action => 'comments', :display_name => current_user.display_name %>
            </li>
            <li>
-             <%= link_to t('user.view.my settings'), :controller => 'user', :action => 'account', :display_name => current_user.display_name %>
+             <%= link_to t('.my settings'), :controller => 'user', :action => 'account', :display_name => current_user.display_name %>
            </li>
  
            <% if current_user.blocks.exists? %>
              <li>
-               <%= link_to t('user.view.blocks on me'), :controller => 'user_blocks', :action => 'blocks_on', :display_name => current_user.display_name %>
+               <%= link_to t('.blocks on me'), :controller => 'user_blocks', :action => 'blocks_on', :display_name => current_user.display_name %>
                <span class='count-number'><%= number_with_delimiter(current_user.blocks.active.size) %></span>
              </li>
            <% end %>
  
            <% if current_user and current_user.moderator? and current_user.blocks_created.exists? %>
              <li>
-               <%= link_to t('user.view.blocks by me'), :controller => 'user_blocks', :action => 'blocks_by', :display_name => current_user.display_name %>
+               <%= link_to t('.blocks by me'), :controller => 'user_blocks', :action => 'blocks_by', :display_name => current_user.display_name %>
                <span class='count-number'><%= number_with_delimiter(current_user.blocks_created.active.size) %></span>
              </li>
            <% end %>
          <ul class='secondary-actions clearfix'>
  
            <li>
-             <%= link_to t('user.view.edits'), :controller => 'changeset', :action => 'list', :display_name => @this_user.display_name %>
-             <span class='count-number'><%= number_with_delimiter(@this_user.changesets.size) %></span>
+             <%= link_to t('.edits'), :controller => 'changeset', :action => 'list', :display_name => @user.display_name %>
+             <span class='count-number'><%= number_with_delimiter(@user.changesets.size) %></span>
            </li>
            <li>
-             <%= link_to t('user.view.notes'), :controller => 'notes', :action=> 'mine' %>
+             <%= link_to t('.notes'), :controller => 'notes', :action=> 'mine' %>
            </li>
            <li>
-             <%= link_to t('user.view.traces'), :controller => 'trace', :action => 'list', :display_name => @this_user.display_name %>
-             <span class='count-number'><%= number_with_delimiter(@this_user.traces.size) %></span>
+             <%= link_to t('.traces'), :controller => 'traces', :action => 'list', :display_name => @user.display_name %>
+             <span class='count-number'><%= number_with_delimiter(@user.traces.size) %></span>
            </li>
  
            <!-- Displaying another user's profile page -->
  
            <li>
-             <%= link_to t('user.view.send message'), :controller => 'message', :action => 'new', :display_name => @this_user.display_name %>
+             <%= link_to t('.send message'), new_message_path(@user) %>
            </li>
            <li>
-             <%= link_to t('user.view.diary'), :controller => 'diary_entry', :action => 'list', :display_name => @this_user.display_name %>
-             <span class='count-number'><%= number_with_delimiter(@this_user.diary_entries.size) %></span>
+             <%= link_to t('.diary'), :controller => 'diary_entry', :action => 'list', :display_name => @user.display_name %>
+             <span class='count-number'><%= number_with_delimiter(@user.diary_entries.size) %></span>
            </li>
            <li>
-             <%= link_to t('user.view.comments'), :controller => 'diary_entry', :action => 'comments', :display_name => @this_user.display_name %>
+             <%= link_to t('.comments'), :controller => 'diary_entry', :action => 'comments', :display_name => @user.display_name %>
            </li>
            <li>
-             <% if current_user and current_user.is_friends_with?(@this_user) %>
-               <%= link_to t('user.view.remove as friend'), remove_friend_path(:display_name => @this_user.display_name), :method => :post %>
+             <% if current_user and current_user.is_friends_with?(@user) %>
+               <%= link_to t('.remove as friend'), remove_friend_path(:display_name => @user.display_name), :method => :post %>
              <% elsif current_user %>
-               <%= link_to t('user.view.add as friend'), make_friend_path(:display_name => @this_user.display_name), :method => :post %>
+               <%= link_to t('.add as friend'), make_friend_path(:display_name => @user.display_name), :method => :post %>
              <% else %>
-               <%= link_to t('user.view.add as friend'), make_friend_path(:display_name => @this_user.display_name) %>
+               <%= link_to t('.add as friend'), make_friend_path(:display_name => @user.display_name) %>
              <% end %>
            </li>
  
-           <% if @this_user.blocks.exists? %>
+           <% if @user.blocks.exists? %>
              <li>
-               <%= link_to t('user.view.block_history'), :controller => 'user_blocks', :action => 'blocks_on', :display_name => @this_user.display_name %>
-               <span class='count-number'><%= number_with_delimiter(@this_user.blocks.active.size) %></span>
+               <%= link_to t('.block_history'), :controller => 'user_blocks', :action => 'blocks_on', :display_name => @user.display_name %>
+               <span class='count-number'><%= number_with_delimiter(@user.blocks.active.size) %></span>
              </li>
            <% end %>
  
-           <% if @this_user.moderator? and @this_user.blocks_created.exists? %>
+           <% if @user.moderator? and @user.blocks_created.exists? %>
              <li>
-               <%= link_to t('user.view.moderator_history'), :controller => 'user_blocks', :action => 'blocks_by', :display_name => @this_user.display_name %>
-               <span class='count-number'><%= number_with_delimiter(@this_user.blocks_created.active.size) %></span>
+               <%= link_to t('.moderator_history'), :controller => 'user_blocks', :action => 'blocks_by', :display_name => @user.display_name %>
+               <span class='count-number'><%= number_with_delimiter(@user.blocks_created.active.size) %></span>
              </li>
            <% end %>
  
            <% if current_user and current_user.moderator? %>
              <li>
-             <%= link_to t('user.view.create_block'), :controller => 'user_blocks', :action => 'new', :display_name => @this_user.display_name %>
+             <%= link_to t('.create_block'), :controller => 'user_blocks', :action => 'new', :display_name => @user.display_name %>
              </li>
            <% end %>
  
-           <% if current_user and @this_user.id != current_user.id %>
++          <% if current_user and @user.id != current_user.id %>
 +            <li>
-               <%= report_link(t(".report"), @this_user) %>
++              <%= report_link(t(".report"), @user) %>
 +            </li>
 +          <% end %>
          </ul>
  
        <% end %>
        <% if current_user and current_user.administrator? %>
  
          <ul class='secondary-actions clearfix'>
-           <% if ["active", "confirmed"].include? @this_user.status %>
+           <% if ["active", "confirmed"].include? @user.status %>
              <li>
-               <%= link_to t('user.view.deactivate_user'), set_status_user_path(:status => 'pending', :display_name => @this_user.display_name), :data => { :confirm => t('user.view.confirm') } %>
+               <%= link_to t('.deactivate_user'), set_status_user_path(:status => 'pending', :display_name => @user.display_name), :data => { :confirm => t('.confirm') } %>
              </li>
-           <% elsif ["pending"].include? @this_user.status %>
+           <% elsif ["pending"].include? @user.status %>
              <li>
-               <%= link_to t('user.view.activate_user'), set_status_user_path(:status => 'active', :display_name => @this_user.display_name), :data => { :confirm => t('user.view.confirm') } %>
+               <%= link_to t('.activate_user'), set_status_user_path(:status => 'active', :display_name => @user.display_name), :data => { :confirm => t('.confirm') } %>
              </li>
            <% end %>
  
-           <% if ["active", "suspended"].include? @this_user.status %>
+           <% if ["active", "suspended"].include? @user.status %>
              <li>
-               <%= link_to t('user.view.confirm_user'), set_status_user_path(:status => 'confirmed', :display_name => @this_user.display_name), :data => { :confirm => t('user.view.confirm') } %>
+               <%= link_to t('.confirm_user'), set_status_user_path(:status => 'confirmed', :display_name => @user.display_name), :data => { :confirm => t('.confirm') } %>
              </li>
            <% end %>
              <li>
-               <% if ["pending", "active", "confirmed", "suspended"].include? @this_user.status %>
-                 <%= link_to t('user.view.hide_user'), set_status_user_path(:status => 'deleted', :display_name => @this_user.display_name), :data => { :confirm => t('user.view.confirm') } %>
+               <% if ["pending", "active", "confirmed", "suspended"].include? @user.status %>
+                 <%= link_to t('.hide_user'), set_status_user_path(:status => 'deleted', :display_name => @user.display_name), :data => { :confirm => t('.confirm') } %>
              <% else %>
-               <%= link_to t('user.view.unhide_user'), set_status_user_path(:status => 'active', :display_name => @this_user.display_name), :data => { :confirm => t('user.view.confirm') } %>
+               <%= link_to t('.unhide_user'), set_status_user_path(:status => 'active', :display_name => @user.display_name), :data => { :confirm => t('.confirm') } %>
              </li>
            <% end %>
            <li>
-             <%= link_to t('user.view.delete_user'), delete_user_path(:display_name => @this_user.display_name), :data => { :confirm => t('user.view.confirm') } %>
+             <%= link_to t('.delete_user'), delete_user_path(:display_name => @user.display_name), :data => { :confirm => t('.confirm') } %>
            </li>
          </ul>
  
  
        <p class='deemphasize'>
          <small>
-           <%= t 'user.view.mapper since' %> <%= l @this_user.creation_time.to_date, :format => :long %>
-           <% unless @this_user.terms_agreed %>
+           <%= t '.mapper since' %> <%= l @user.creation_time.to_date, :format => :long %>
+           <% unless @user.terms_agreed %>
              |
-             <%= t 'user.view.ct status' %>
-             <% if @this_user.terms_seen? -%>
-               <%= t 'user.view.ct declined' %>
+             <%= t '.ct status' %>
+             <% if @user.terms_seen? -%>
+               <%= t '.ct declined' %>
              <% else -%>
-               <%= t 'user.view.ct undecided' %>
+               <%= t '.ct undecided' %>
              <% end -%>
            <% end -%>
          </small>
        </p>
      </div>
  
-     <div class="user-description richtext"><%= @this_user.description.to_html %></div>
+     <div class="user-description richtext"><%= @user.description.to_html %></div>
  
    </div>
  
    <% if current_user and current_user.administrator? -%>
      <div class='admin-user-info deemphasize'>
-       <small><b><%= t 'user.view.email address' %></b> <%= @this_user.email %></small>
-       <% unless @this_user.creation_ip.nil? -%>
-         <small><b><%= t 'user.view.created from' %></b> <%= @this_user.creation_ip %></small>
+       <small><b><%= t '.email address' %></b> <%= @user.email %></small>
+       <% unless @user.creation_ip.nil? -%>
+         <small><b><%= t '.created from' %></b> <%= @user.creation_ip %></small>
        <% end -%>
-       <small><b><%= t 'user.view.status' %></b> <%= @this_user.status.capitalize %></small>
-       <small><b><%= t 'user.view.spam score' %></b> <%= @this_user.spam_score %></small>
+       <small><b><%= t '.status' %></b> <%= @user.status.capitalize %></small>
+       <small><b><%= t '.spam score' %></b> <%= @user.spam_score %></small>
      </div>
    <% end -%>
  
  <% end %>
  
-   <% if current_user and @this_user.id == current_user.id %>
-     <% if @this_user.home_lat.nil? or @this_user.home_lon.nil? %>
+   <% if current_user and @user.id == current_user.id %>
+     <% if @user.home_lat.nil? or @user.home_lon.nil? %>
        <div id="map" class="content_map">
-         <p id="no_home_location"><%= raw(t 'user.view.if set location', :settings_link => (link_to t('user.view.settings_link_text'), :controller => 'user', :action => 'account', :display_name => current_user.display_name)) %></p>
+         <p id="no_home_location"><%= raw(t '.if set location', :settings_link => (link_to t('.settings_link_text'), :controller => 'user', :action => 'account', :display_name => current_user.display_name)) %></p>
        </div>
      <% else %>
        <% content_for :head do %>
        <%= content_tag "div", "", :id => "map", :class => "content_map", :data => {:user => user_data} %>
      <% end %>
  
-     <% friends = @this_user.friends.collect { |f| f.befriendee } %>
-     <% nearby = @this_user.nearby - friends %>
+     <% friends = @user.friends.collect { |f| f.befriendee } %>
+     <% nearby = @user.nearby - friends %>
  
    <div class="activity-block column-1">
-     <h3><%= t 'user.view.my friends' %></h3>
+     <h3><%= t '.my friends' %></h3>
  
      <% if friends.empty? %>
-       <%= t 'user.view.no friends' %>
+       <%= t '.no friends' %>
      <% else %>
        <ul class='secondary-actions clearfix'>
-         <li><%= link_to t('user.view.friends_changesets'), friend_changesets_path %></li>
-         <li><%= link_to t('user.view.friends_diaries'), friend_diaries_path %></li>
+         <li><%= link_to t('.friends_changesets'), friend_changesets_path %></li>
+         <li><%= link_to t('.friends_diaries'), friend_diaries_path %></li>
        </ul>
        <div id="friends-container">
          <%= render :partial => "contact", :collection => friends, :locals => {:type => "friend"} %>
    </div>
  
    <div class="activity-block column-1">
-     <h3><%= t 'user.view.nearby users' %></h3>
+     <h3><%= t '.nearby users' %></h3>
  
      <% if nearby.empty? %>
-       <%= t 'user.view.no nearby users' %>
+       <%= t '.no nearby users' %>
      <% else %>
        <ul class='secondary-actions clearfix'>
-         <li><%= link_to t('user.view.nearby_changesets'), nearby_changesets_path %></li>
-         <li><%= link_to t('user.view.nearby_diaries'), nearby_diaries_path %></li>
+         <li><%= link_to t('.nearby_changesets'), nearby_changesets_path %></li>
+         <li><%= link_to t('.nearby_diaries'), nearby_diaries_path %></li>
        </ul>
        <div id="nearbyusers">
          <%= render :partial => "contact", :collection => nearby, :locals => {:type => "nearby mapper"} %>
diff --combined config/locales/en.yml
index 9bb423857e8f02814dc3da5ea30b6e5efa64803a,a7efaf98566a9426c432ed7a34b63f3b836fc017..17549940a59b0a24cef04964173e4028f2350c9d
@@@ -207,7 -207,6 +207,7 @@@ en
        reopened_by: "Reactivated by %{user} <abbr title='%{exact_time}'>%{when} ago</abbr>"
        reopened_by_anonymous: "Reactivated by anonymous <abbr title='%{exact_time}'>%{when} ago</abbr>"
        hidden_by: "Hidden by %{user} <abbr title='%{exact_time}'>%{when} ago</abbr>"
 +      report: Report this note
      query:
        title: "Query Features"
        introduction: "Click on the map to find nearby features."
        edit_link: Edit this entry
        hide_link: Hide this entry
        confirm: Confirm
 +      report: Report this entry
      diary_comment:
        comment_from: "Comment from %{link_user} on %{comment_created_at}"
        hide_link: Hide this comment
        confirm: Confirm
 +      report: Report this comment
      location:
        location: "Location:"
        view: "View"
        ago: "%{ago} ago"
        newer_comments: "Newer Comments"
        older_comments: "Older Comments"
-   export:
-     title: "Export"
-     start:
-       area_to_export: "Area to Export"
-       manually_select: "Manually select a different area"
-       format_to_export: "Format to Export"
-       osm_xml_data: "OpenStreetMap XML Data"
-       map_image: "Map Image (shows standard layer)"
-       embeddable_html: "Embeddable HTML"
-       licence: "Licence"
-       export_details: 'OpenStreetMap data is licensed under the <a href="https://opendatacommons.org/licenses/odbl/1.0/">Open Data Commons Open Database License</a> (ODbL).'
-       too_large:
-         advice: "If the above export fails, please consider using one of the sources listed below:"
-         body: "This area is too large to be exported as OpenStreetMap XML Data. Please zoom in or select a smaller area, or use one of the sources listed below for bulk data downloads."
-         planet:
-           title: "Planet OSM"
-           description: "Regularly-updated copies of the complete OpenStreetMap database"
-         overpass:
-           title: "Overpass API"
-           description: "Download this bounding box from a mirror of the OpenStreetMap database"
-         geofabrik:
-           title: "Geofabrik Downloads"
-           description: "Regularly-updated extracts of continents, countries, and selected cities"
-         metro:
-           title: "Metro Extracts"
-           description: "Extracts for major world cities and their surrounding areas"
-         other:
-           title: "Other Sources"
-           description: "Additional sources listed on the OpenStreetMap wiki"
-       options: "Options"
-       format: "Format"
-       scale: "Scale"
-       max: "max"
-       image_size: "Image Size"
-       zoom: "Zoom"
-       add_marker: "Add a marker to the map"
-       latitude: "Lat:"
-       longitude: "Lon:"
-       output: "Output"
-       paste_html: "Paste HTML to embed in website"
-       export_button: "Export"
    geocoder:
      search:
        title:
      results:
        no_results: "No results found"
        more_results: "More results"
 +  issues:
 +    index:
 +      title: Issues
 +      select_status: Select Status
 +      select_type: Select Type
 +      select_last_updated_by: Select Last Updated By
 +      reported_user: Reported User
 +      not_updated: Not Updated
 +      search: Search
 +      search_guidance: "Search Issues:"
 +      user_not_found: User does not exist
 +      issues_not_found: No such issues found
 +      status: Status
 +      reports: Reports
 +      last_updated: Last Updated
 +      last_updated_time_html: "<abbr title='%{title}'>%{time} ago</abbr>"
 +      last_updated_time_user_html: "<abbr title='%{title}'>%{time} ago</abbr> by %{user}"
 +      link_to_reports: View Reports
 +      reported_user: Reported User
 +      reports_count:
 +        one: "1 Report"
 +        other: "%{count} Reports"
 +      reported_item: Reported Item
 +      states:
 +        ignored: Ignored
 +        open: Open
 +        resolved: Resolved
 +    update:
 +      new_report: Your report has been registered sucessfully
 +      successful_update: Your report has been updated successfully
 +      provide_details: Please provide the required details
 +    show:
 +      title: "%{status} Issue #%{issue_id}"
 +      reports:
 +        zero: No reports
 +        one: 1 report
 +        other: "%{count} reports"
 +      report_created_at: "First reported at %{datetime}"
 +      last_resolved_at: "Last resolved at %{datetime}"
 +      last_updated_at: "Last updated at %{datetime} by %{displayname}"
 +      resolve: Resolve
 +      ignore: Ignore
 +      reopen: Reopen
 +      reports_of_this_issue: Reports of this Issue
 +      read_reports: Read Reports
 +      new_reports: New Reports
 +      other_issues_against_this_user: Other issues against this user
 +      no_other_issues: No other issues against this user.
 +      comments_on_this_issue: Comments on this issue
 +    resolve:
 +      resolved: Issue status has been set to 'Resolved'
 +    ignore:
 +      ignored: Issue status has been set to 'Ignored'
 +    reopen:
 +      reopened: Issue status has been set to 'Open'
 +    comments:
 +      created_at: "On %{datetime}"
 +      reassign_param: Reassign Issue?
 +    reports:
 +      updated_at: "On %{datetime}"
 +      reported_by_html: "Reported as %{category} by %{user}"
 +  issue_comments:
 +    create:
 +      comment_created: Your comment was successfully created
 +  reports:
 +    new:
 +      title_html: "Report %{link}"
 +      missing_params: "Cannot create a new report"
 +      details: Please provide some more details about the problem (required).
 +      select: "Select a reason for your report:"
 +      disclaimer:
 +        intro: "Before sending your report to the site moderators, please ensure that:"
 +        not_just_mistake: You are certain that the problem is not just a mistake
 +        unable_to_fix: You are unable to fix the problem yourself or with the help of your fellow community members
 +        resolve_with_user: You have already tried to resolve the problem with the user concerned
 +      categories:
 +        diary_entry:
 +          spam: This diary entry is/contains spam
 +          offensive: This diary entry is obscene/offensive
 +          threat: This diary entry contains a threat
 +          other: Other
 +        diary_comment:
 +          spam: This diary comment is/contains spam
 +          offensive: This diary comment is obscene/offensive
 +          threat: This diary comment contains a threat
 +          other: Other
 +        user:
 +          spam: This user profile is/contains spam
 +          offensive: This user profile is obscene/offensive
 +          threat: This user profile contains a threat
 +          vandal: This user is a vandal
 +          other: Other
 +        note:
 +          spam: This note is spam
 +          personal: This note contains personal data
 +          abusive: This note is abusive
 +          other: Other
 +    create:
 +      successful_report: Your report has been registered sucessfully
 +      provide_details: Please provide the required details      
    layouts:
      project_name:
        # in <title>
      edit: Edit
      history: History
      export: Export
 +    issues: Issues
      data: Data
      export_data: Export Data
      gps_traces: GPS Traces
        text: Make a Donation
      learn_more: "Learn More"
      more: More
-   license_page:
-     foreign:
-       title: About this translation
-       text: In the event of a conflict between this translated page and %{english_original_link}, the English page shall take precedence
-       english_link: the English original
-     native:
-       title: About this page
-       text: You are viewing the English version of the copyright page. You can go back to the %{native_link} of this page or you can stop reading about copyright and %{mapping_link}.
-       native_link: THIS_LANGUAGE_NAME_HERE version
-       mapping_link: start mapping
-     legal_babble:
-       title_html: Copyright and License
-       intro_1_html: |
-         OpenStreetMap<sup><a href="#trademarks">&reg;</a></sup> is <i>open data</i>, licensed under the <a
-         href="https://opendatacommons.org/licenses/odbl/">Open Data
-         Commons Open Database License</a> (ODbL) by the  <a
-         href="https://osmfoundation.org/">OpenStreetMap Foundation</a> (OSMF).
-       intro_2_html: |
-         You are free to copy, distribute, transmit and adapt our data,
-         as long as you credit OpenStreetMap and its
-         contributors. If you alter or build upon our data, you
-         may distribute the result only under the same licence. The
-         full <a href="https://opendatacommons.org/licenses/odbl/1.0/">legal
-         code</a> explains your rights and responsibilities.
-       intro_3_html: |
-         The cartography in our map tiles, and our documentation, are
-         licensed under the <a href="https://creativecommons.org/licenses/by-sa/2.0/">Creative
-         Commons Attribution-ShareAlike 2.0</a> license (CC BY-SA).
-       credit_title_html: How to credit OpenStreetMap
-       credit_1_html: |
-         We require that you use the credit &ldquo;&copy; OpenStreetMap
-         contributors&rdquo;.
-       credit_2_html: |
-         You must also make it clear that the data is available under the Open
-         Database License, and if using our map tiles, that the cartography is
-         licensed as CC BY-SA. You may do this by linking to
-         <a href="https://www.openstreetmap.org/copyright">this copyright page</a>.
-         Alternatively, and as a requirement if you are distributing OSM in a
-         data form, you can name and link directly to the license(s). In media
-         where links are not possible (e.g. printed works), we suggest you
-         direct your readers to openstreetmap.org (perhaps by expanding
-         'OpenStreetMap' to this full address), to opendatacommons.org, and
-         if relevant, to creativecommons.org.
-       credit_3_html: |
-         For a browsable electronic map, the credit should appear in the corner of the map.
-         For example:
-       attribution_example:
-         alt: Example of how to attribute OpenStreetMap on a webpage
-         title: Attribution example
-       more_title_html: Finding out more
-       more_1_html: |
-         Read more about using our data, and how to credit us, at the <a
-         href="https://osmfoundation.org/Licence">OSMF Licence page</a>.
-       more_2_html: |
-         Although OpenStreetMap is open data, we cannot provide a
-         free-of-charge map API for third-parties.
-         See our <a href="https://operations.osmfoundation.org/policies/api/">API Usage Policy</a>,
-         <a href="https://operations.osmfoundation.org/policies/tiles/">Tile Usage Policy</a>
-         and <a href="https://operations.osmfoundation.org/policies/nominatim/">Nominatim Usage Policy</a>.
-       contributors_title_html: Our contributors
-       contributors_intro_html: |
-         Our contributors are thousands of individuals. We also include
-         openly-licensed data from national mapping agencies
-         and other sources, among them:
-       contributors_at_html: |
-         <strong>Austria</strong>: Contains data from
-         <a href="https://data.wien.gv.at/">Stadt Wien</a> (under
-         <a href="https://creativecommons.org/licenses/by/3.0/at/deed.de">CC BY</a>),
-         <a href="https://www.vorarlberg.at/vorarlberg/bauen_wohnen/bauen/vermessung_geoinformation/weitereinformationen/services/wmsdienste.htm">Land Vorarlberg</a> and
-         Land Tirol (under <a href="https://www.tirol.gv.at/applikationen/e-government/data/nutzungsbedingungen/">CC BY AT with amendments</a>).
-       contributors_ca_html: |
-         <strong>Canada</strong>: Contains data from
-         GeoBase&reg;, GeoGratis (&copy; Department of Natural
-         Resources Canada), CanVec (&copy; Department of Natural
-         Resources Canada), and StatCan (Geography Division,
-         Statistics Canada).
-       contributors_fi_html: |
-         <strong>Finland</strong>: Contains data from the
-         National Land Survey of Finland's Topographic Database
-         and other datasets, under the
-         <a href="https://www.maanmittauslaitos.fi/en/opendata-licence-version1">NLSFI License</a>.
-       contributors_fr_html: |
-         <strong>France</strong>: Contains data sourced from
-         Direction Générale des Impôts.
-       contributors_nl_html: |
-         <strong>Netherlands</strong>: Contains &copy; AND data, 2007
-         (<a href="https://www.and.com">www.and.com</a>)
-       contributors_nz_html: |
-         <strong>New Zealand</strong>: Contains data sourced from
-         Land Information New Zealand. Crown Copyright reserved.
-       contributors_si_html: |
-         <strong>Slovenia</strong>: Contains data from the
-         <a href="http://www.gu.gov.si/en/">Surveying and Mapping Authority</a> and
-         <a href="http://www.mkgp.gov.si/en/">Ministry of Agriculture, Forestry and Food</a>
-         (public information of Slovenia).
-       contributors_za_html: |
-         <strong>South Africa</strong>: Contains data sourced from
-         <a href="http://www.ngi.gov.za/">Chief Directorate:
-         National Geo-Spatial Information</a>, State copyright reserved.
-       contributors_gb_html: |
-         <strong>United Kingdom</strong>: Contains Ordnance
-         Survey data &copy; Crown copyright and database right
-         2010-12.
-       contributors_footer_1_html: |
-         For further details of these, and other sources that have been used
-         to help improve OpenStreetMap, please see the <a
-         href="https://wiki.openstreetmap.org/wiki/Contributors">Contributors
-         page</a> on the OpenStreetMap Wiki.
-       contributors_footer_2_html: |
-         Inclusion of data in OpenStreetMap does not imply that the original
-         data provider endorses OpenStreetMap, provides any warranty, or
-         accepts any liability.
-       infringement_title_html: Copyright infringement
-       infringement_1_html: |
-         OSM contributors are reminded never to add data from any
-         copyrighted sources (e.g. Google Maps or printed maps) without
-         explicit permission from the copyright holders.
-       infringement_2_html: |
-         If you believe that copyrighted material has been inappropriately
-         added to the OpenStreetMap database or this site, please refer
-         to our <a href="https://www.osmfoundation.org/wiki/License/Takedown_procedure">takedown
-         procedure</a> or file directly at our
-         <a href="http://dmca.openstreetmap.org/">on-line filing page</a>.
-       trademarks_title_html: <span id="trademarks"></span>Trademarks
-       trademarks_1_html: |
-         OpenStreetMap, the magnifying glass logo and State of the Map are registered trademarks of the OpenStreetMap Foundation. If you have questions about your use of the marks, please see our <a href="https://wiki.osmfoundation.org/wiki/Trademark_Policy">Trademark Policy</a>.
-   welcome_page:
-     title: Welcome!
-     introduction_html: |
-       Welcome to OpenStreetMap, the free and editable map of the world. Now that you're signed
-       up, you're all set to get started mapping. Here's a quick guide with the most important
-       things you need to know.
-     whats_on_the_map:
-       title: What's on the Map
-       on_html: |
-         OpenStreetMap is a place for mapping things that are both <em>real and current</em> -
-         it includes millions of buildings, roads, and other details about places. You can map
-         whatever real-world features are interesting to you.
-       off_html: |
-         What it <em>doesn't</em> include is opinionated data like ratings, historical or
-         hypothetical features, and data from copyrighted sources. Unless you have special
-         permission, don't copy from online or paper maps.
-     basic_terms:
-       title: Basic Terms For Mapping
-       paragraph_1_html: |
-         OpenStreetMap has some of its own lingo. Here are a few key words that'll come in handy.
-       editor_html: |
-         An <strong>editor</strong> is a program or website you can use to edit the map.
-       node_html: |
-         A <strong>node</strong> is a point on the map, like a single restaurant or a tree.
-       way_html: |
-         A <strong>way</strong> is a line or area, like a road, stream, lake or building.
-       tag_html: |
-         A <strong>tag</strong> is a bit of data about a node or way, like a
-         restaurant's name or a road's speed limit.
-     rules:
-       title: Rules!
-       paragraph_1_html: |
-         OpenStreetMap has few formal rules but we expect all participants to collaborate
-         with, and communicate with, the community. If you are considering
-         any activities other than editing by hand, please read and follow the guidelines on
-         <a href='https://wiki.openstreetmap.org/wiki/Import/Guidelines'>Imports</a> and
-         <a href='https://wiki.openstreetmap.org/wiki/Automated_Edits_code_of_conduct'>Automated Edits</a>.
-     questions:
-       title: Any questions?
-       paragraph_1_html: |
-         OpenStreetMap has several resources for learning about the project, asking and answering
-         questions, and collaboratively discussing and documenting mapping topics.
-         <a href='%{help_url}'>Get help here</a>.
-     start_mapping: Start Mapping
-     add_a_note:
-       title: No Time To Edit? Add a Note!
-       paragraph_1_html: |
-         If you just want something small fixed and don't have the time to sign up and learn how to edit, it's
-         easy to add a note.
-       paragraph_2_html: |
-         Just go to <a href='%{map_url}'>the map</a> and click the note icon:
-         <span class='icon note'></span>. This will add a marker to the map, which you can move
-         by dragging. Add your message, then click save, and other mappers will investigate.
-   fixthemap:
-     title: Report a problem / Fix the map
-     how_to_help:
-       title: How to Help
-       join_the_community:
-         title: Join the community
-         explanation_html: |
-           If you have noticed a problem with our map data, for example a road is missing or your address, the best way to
-           proceed is to join the OpenStreetMap community and add or repair the data yourself.
-       add_a_note:
-         instructions_html: |
-           Just click <a class='icon note'></a> or the same icon on the map display.
-           This will add a marker to the map, which you can move
-           by dragging. Add your message, then click save, and other mappers will investigate.
-     other_concerns:
-       title: Other concerns
-       explanation_html: |
-         If you have concerns about how our data is being used or about the contents please consult our
-         <a href='/copyright'>copyright page</a> for more legal information, or contact the appropriate
-         <a href='https://wiki.osmfoundation.org/wiki/Working_Groups'>OSMF working group</a>.
-   help_page:
-     title: Getting Help
-     introduction: |
-       OpenStreetMap has several resources for learning about the project, asking and answering questions,
-       and collaboratively discussing and documenting mapping topics.
-     welcome:
-       url: /welcome
-       title: Welcome to OSM
-       description: Start with this quick guide covering the OpenStreetMap basics.
-     beginners_guide:
-       url: https://wiki.openstreetmap.org/wiki/Beginners%27_guide
-       title: Beginners' Guide
-       description: Community maintained guide for beginners.
-     help:
-       url: https://help.openstreetmap.org/
-       title: help.openstreetmap.org
-       description: Ask a question or look up answers on OSM's question-and-answer site.
-     mailing_lists:
-       url: https://lists.openstreetmap.org/
-       title: Mailing Lists
-       description: Ask a question or discuss interesting matters on a wide range of topical or regional mailing lists.
-     forums:
-       url: https://forum.openstreetmap.org/
-       title: Forums
-       description: Questions and discussions for those that prefer a bulletin board style interface.
-     irc:
-       url: https://irc.openstreetmap.org/
-       title: IRC
-       description: Interactive chat in many different languages and on many topics.
-     switch2osm:
-       url: https://switch2osm.org/
-       title: switch2osm
-       description: Help for companies and organisations switching to OpenStreetMap based maps and other services.
-     wiki:
-       url: https://wiki.openstreetmap.org/
-       title: wiki.openstreetmap.org
-       description: Browse the wiki for in-depth OSM documentation.
-   about_page:
-     next: Next
-     copyright_html: <span>&copy;</span>OpenStreetMap<br>contributors
-     used_by: "%{name} powers map data on thousands of web sites, mobile apps, and hardware devices"
-     lede_text: |
-       OpenStreetMap is built by a community of mappers that contribute and maintain data
-       about roads, trails, cafés, railway stations, and much more, all over the world.
-     local_knowledge_title: Local Knowledge
-     local_knowledge_html: |
-       OpenStreetMap emphasizes local knowledge. Contributors use
-       aerial imagery, GPS devices, and low-tech field maps to verify that OSM
-       is accurate and up to date.
-     community_driven_title: Community Driven
-     community_driven_html: |
-       OpenStreetMap's community is diverse, passionate, and growing every day.
-       Our contributors include enthusiast mappers, GIS professionals, engineers
-       running the OSM servers, humanitarians mapping disaster-affected areas,
-       and many more.
-       To learn more about the community, see the
-       <a href='https://blog.openstreetmap.org'>OpenStreetMap Blog</a>,
-       <a href='%{diary_path}'>user diaries</a>,
-       <a href='https://blogs.openstreetmap.org/'>community blogs</a>, and
-       the <a href='https://www.osmfoundation.org/'>OSM Foundation</a> website.
-     open_data_title: Open Data
-     open_data_html: |
-       OpenStreetMap is <i>open data</i>: you are free to use it for any purpose
-       as long as you credit OpenStreetMap and its contributors. If you alter or
-       build upon the data in certain ways, you may distribute the result only
-       under the same licence. See the <a href='%{copyright_path}'>Copyright and
-       License page</a> for details.
-     legal_title: Legal
-     legal_html: |
-       This site and many other related services are formally operated by the
-       <a href='https://osmfoundation.org/'>OpenStreetMap Foundation</a> (OSMF)
-       on behalf of the community. Use of all OSMF operated services is subject
-       to our <a href="https://wiki.openstreetmap.org/wiki/Acceptable_Use_Policy">
-       Acceptable Use Policies</a> and our <a href="https://wiki.osmfoundation.org/wiki/Privacy_Policy">Privacy Policy</a>
-       <br>
-       Please <a href='https://osmfoundation.org/Contact'>contact the OSMF</a>
-       if you have licensing, copyright or other legal questions.
-       <br>
-       OpenStreetMap, the magnifying glass logo and State of the Map are <a href="https://wiki.osmfoundation.org/wiki/Trademark_Policy">registered trademarks of the OSMF</a>.
-     partners_title: Partners
    notifier:
      diary_comment_notification:
        subject: "[OpenStreetMap] %{user} commented on a diary entry"
          partial_changeset_without_comment: "without comment"
        details: "More details about the changeset can be found at %{url}."
        unsubscribe: 'To unsubscribe from updates to this changeset, visit %{url} and click "Unsubscribe".'
-   message:
+   messages:
      inbox:
        title: "Inbox"
        my_inbox: "My Inbox"
        unread_button: "Mark as unread"
        read_button: "Mark as read"
        reply_button: "Reply"
-       delete_button: "Delete"
+       destroy_button: "Delete"
      new:
        title: "Send message"
        send_message_to: "Send a new message to %{name}"
        people_mapping_nearby: "people mapping nearby"
      reply:
        wrong_user: "You are logged in as `%{user}' but the message you have asked to reply to was not sent to that user. Please login as the correct user in order to reply."
-     read:
+     show:
        title: "Read message"
        from: "From"
        subject: "Subject"
        date: "Date"
        reply_button: "Reply"
        unread_button: "Mark as unread"
-       delete_button: "Delete"
+       destroy_button: "Delete"
        back: "Back"
        to: "To"
        wrong_user: "You are logged in as `%{user}' but the message you have asked to read was not sent by or to that user. Please login as the correct user in order to read it."
      sent_message_summary:
-       delete_button: "Delete"
+       destroy_button: "Delete"
      mark:
        as_read: "Message marked as read"
        as_unread: "Message marked as unread"
-     delete:
-       deleted: "Message deleted"
+     destroy:
+       destroyed: "Message deleted"
    site:
+     about:
+       next: Next
+       copyright_html: <span>&copy;</span>OpenStreetMap<br>contributors
+       used_by: "%{name} powers map data on thousands of web sites, mobile apps, and hardware devices"
+       lede_text: |
+         OpenStreetMap is built by a community of mappers that contribute and maintain data
+         about roads, trails, cafés, railway stations, and much more, all over the world.
+       local_knowledge_title: Local Knowledge
+       local_knowledge_html: |
+         OpenStreetMap emphasizes local knowledge. Contributors use
+         aerial imagery, GPS devices, and low-tech field maps to verify that OSM
+         is accurate and up to date.
+       community_driven_title: Community Driven
+       community_driven_html: |
+         OpenStreetMap's community is diverse, passionate, and growing every day.
+         Our contributors include enthusiast mappers, GIS professionals, engineers
+         running the OSM servers, humanitarians mapping disaster-affected areas,
+         and many more.
+         To learn more about the community, see the
+         <a href='https://blog.openstreetmap.org'>OpenStreetMap Blog</a>,
+         <a href='%{diary_path}'>user diaries</a>,
+         <a href='https://blogs.openstreetmap.org/'>community blogs</a>, and
+         the <a href='https://www.osmfoundation.org/'>OSM Foundation</a> website.
+       open_data_title: Open Data
+       open_data_html: |
+         OpenStreetMap is <i>open data</i>: you are free to use it for any purpose
+         as long as you credit OpenStreetMap and its contributors. If you alter or
+         build upon the data in certain ways, you may distribute the result only
+         under the same licence. See the <a href='%{copyright_path}'>Copyright and
+         License page</a> for details.
+       legal_title: Legal
+       legal_html: |
+         This site and many other related services are formally operated by the
+         <a href='https://osmfoundation.org/'>OpenStreetMap Foundation</a> (OSMF)
+         on behalf of the community. Use of all OSMF operated services is subject
+         to our <a href="https://wiki.openstreetmap.org/wiki/Acceptable_Use_Policy">
+         Acceptable Use Policies</a> and our <a href="https://wiki.osmfoundation.org/wiki/Privacy_Policy">Privacy Policy</a>
+         <br>
+         Please <a href='https://osmfoundation.org/Contact'>contact the OSMF</a>
+         if you have licensing, copyright or other legal questions.
+         <br>
+         OpenStreetMap, the magnifying glass logo and State of the Map are <a href="https://wiki.osmfoundation.org/wiki/Trademark_Policy">registered trademarks of the OSMF</a>.
+       partners_title: Partners
+     copyright:
+       foreign:
+         title: About this translation
+         text: In the event of a conflict between this translated page and %{english_original_link}, the English page shall take precedence
+         english_link: the English original
+       native:
+         title: About this page
+         text: You are viewing the English version of the copyright page. You can go back to the %{native_link} of this page or you can stop reading about copyright and %{mapping_link}.
+         native_link: THIS_LANGUAGE_NAME_HERE version
+         mapping_link: start mapping
+       legal_babble:
+         title_html: Copyright and License
+         intro_1_html: |
+           OpenStreetMap<sup><a href="#trademarks">&reg;</a></sup> is <i>open data</i>, licensed under the <a
+           href="https://opendatacommons.org/licenses/odbl/">Open Data
+           Commons Open Database License</a> (ODbL) by the  <a
+           href="https://osmfoundation.org/">OpenStreetMap Foundation</a> (OSMF).
+         intro_2_html: |
+           You are free to copy, distribute, transmit and adapt our data,
+           as long as you credit OpenStreetMap and its
+           contributors. If you alter or build upon our data, you
+           may distribute the result only under the same licence. The
+           full <a href="https://opendatacommons.org/licenses/odbl/1.0/">legal
+           code</a> explains your rights and responsibilities.
+         intro_3_html: |
+           The cartography in our map tiles, and our documentation, are
+           licensed under the <a href="https://creativecommons.org/licenses/by-sa/2.0/">Creative
+           Commons Attribution-ShareAlike 2.0</a> license (CC BY-SA).
+         credit_title_html: How to credit OpenStreetMap
+         credit_1_html: |
+           We require that you use the credit &ldquo;&copy; OpenStreetMap
+           contributors&rdquo;.
+         credit_2_html: |
+           You must also make it clear that the data is available under the Open
+           Database License, and if using our map tiles, that the cartography is
+           licensed as CC BY-SA. You may do this by linking to
+           <a href="https://www.openstreetmap.org/copyright">this copyright page</a>.
+           Alternatively, and as a requirement if you are distributing OSM in a
+           data form, you can name and link directly to the license(s). In media
+           where links are not possible (e.g. printed works), we suggest you
+           direct your readers to openstreetmap.org (perhaps by expanding
+           'OpenStreetMap' to this full address), to opendatacommons.org, and
+           if relevant, to creativecommons.org.
+         credit_3_html: |
+           For a browsable electronic map, the credit should appear in the corner of the map.
+           For example:
+         attribution_example:
+           alt: Example of how to attribute OpenStreetMap on a webpage
+           title: Attribution example
+         more_title_html: Finding out more
+         more_1_html: |
+           Read more about using our data, and how to credit us, at the <a
+           href="https://osmfoundation.org/Licence">OSMF Licence page</a>.
+         more_2_html: |
+           Although OpenStreetMap is open data, we cannot provide a
+           free-of-charge map API for third-parties.
+           See our <a href="https://operations.osmfoundation.org/policies/api/">API Usage Policy</a>,
+           <a href="https://operations.osmfoundation.org/policies/tiles/">Tile Usage Policy</a>
+           and <a href="https://operations.osmfoundation.org/policies/nominatim/">Nominatim Usage Policy</a>.
+         contributors_title_html: Our contributors
+         contributors_intro_html: |
+           Our contributors are thousands of individuals. We also include
+           openly-licensed data from national mapping agencies
+           and other sources, among them:
+         contributors_at_html: |
+           <strong>Austria</strong>: Contains data from
+           <a href="https://data.wien.gv.at/">Stadt Wien</a> (under
+           <a href="https://creativecommons.org/licenses/by/3.0/at/deed.de">CC BY</a>),
+           <a href="https://www.vorarlberg.at/vorarlberg/bauen_wohnen/bauen/vermessung_geoinformation/weitereinformationen/services/wmsdienste.htm">Land Vorarlberg</a> and
+           Land Tirol (under <a href="https://www.tirol.gv.at/applikationen/e-government/data/nutzungsbedingungen/">CC BY AT with amendments</a>).
+         contributors_ca_html: |
+           <strong>Canada</strong>: Contains data from
+           GeoBase&reg;, GeoGratis (&copy; Department of Natural
+           Resources Canada), CanVec (&copy; Department of Natural
+           Resources Canada), and StatCan (Geography Division,
+           Statistics Canada).
+         contributors_fi_html: |
+           <strong>Finland</strong>: Contains data from the
+           National Land Survey of Finland's Topographic Database
+           and other datasets, under the
+           <a href="https://www.maanmittauslaitos.fi/en/opendata-licence-version1">NLSFI License</a>.
+         contributors_fr_html: |
+           <strong>France</strong>: Contains data sourced from
+           Direction Générale des Impôts.
+         contributors_nl_html: |
+           <strong>Netherlands</strong>: Contains &copy; AND data, 2007
+           (<a href="https://www.and.com">www.and.com</a>)
+         contributors_nz_html: |
+           <strong>New Zealand</strong>: Contains data sourced from the
+           <a href="https://data.linz.govt.nz/">LINZ Data Service</a> and
+           licensed for reuse under
+           <a href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a>.
+         contributors_si_html: |
+           <strong>Slovenia</strong>: Contains data from the
+           <a href="http://www.gu.gov.si/en/">Surveying and Mapping Authority</a> and
+           <a href="http://www.mkgp.gov.si/en/">Ministry of Agriculture, Forestry and Food</a>
+           (public information of Slovenia).
+         contributors_za_html: |
+           <strong>South Africa</strong>: Contains data sourced from
+           <a href="http://www.ngi.gov.za/">Chief Directorate:
+           National Geo-Spatial Information</a>, State copyright reserved.
+         contributors_gb_html: |
+           <strong>United Kingdom</strong>: Contains Ordnance
+           Survey data &copy; Crown copyright and database right
+           2010-12.
+         contributors_footer_1_html: |
+           For further details of these, and other sources that have been used
+           to help improve OpenStreetMap, please see the <a
+           href="https://wiki.openstreetmap.org/wiki/Contributors">Contributors
+           page</a> on the OpenStreetMap Wiki.
+         contributors_footer_2_html: |
+           Inclusion of data in OpenStreetMap does not imply that the original
+           data provider endorses OpenStreetMap, provides any warranty, or
+           accepts any liability.
+         infringement_title_html: Copyright infringement
+         infringement_1_html: |
+           OSM contributors are reminded never to add data from any
+           copyrighted sources (e.g. Google Maps or printed maps) without
+           explicit permission from the copyright holders.
+         infringement_2_html: |
+           If you believe that copyrighted material has been inappropriately
+           added to the OpenStreetMap database or this site, please refer
+           to our <a href="https://www.osmfoundation.org/wiki/License/Takedown_procedure">takedown
+           procedure</a> or file directly at our
+           <a href="http://dmca.openstreetmap.org/">on-line filing page</a>.
+         trademarks_title_html: <span id="trademarks"></span>Trademarks
+         trademarks_1_html: |
+           OpenStreetMap, the magnifying glass logo and State of the Map are registered trademarks of the OpenStreetMap Foundation. If you have questions about your use of the marks, please see our <a href="https://wiki.osmfoundation.org/wiki/Trademark_Policy">Trademark Policy</a>.
      index:
        js_1: "You are either using a browser that does not support JavaScript, or you have disabled JavaScript."
        js_2: "OpenStreetMap uses JavaScript for its slippy map."
        potlatch2_unsaved_changes: "You have unsaved changes. (To save in Potlatch 2, you should click save.)"
        id_not_configured: "iD has not been configured"
        no_iframe_support: "Your browser doesn't support HTML iframes, which are necessary for this feature."
+     export:
+       title: "Export"
+       area_to_export: "Area to Export"
+       manually_select: "Manually select a different area"
+       format_to_export: "Format to Export"
+       osm_xml_data: "OpenStreetMap XML Data"
+       map_image: "Map Image (shows standard layer)"
+       embeddable_html: "Embeddable HTML"
+       licence: "Licence"
+       export_details: 'OpenStreetMap data is licensed under the <a href="https://opendatacommons.org/licenses/odbl/1.0/">Open Data Commons Open Database License</a> (ODbL).'
+       too_large:
+         advice: "If the above export fails, please consider using one of the sources listed below:"
+         body: "This area is too large to be exported as OpenStreetMap XML Data. Please zoom in or select a smaller area, or use one of the sources listed below for bulk data downloads."
+         planet:
+           title: "Planet OSM"
+           description: "Regularly-updated copies of the complete OpenStreetMap database"
+         overpass:
+           title: "Overpass API"
+           description: "Download this bounding box from a mirror of the OpenStreetMap database"
+         geofabrik:
+           title: "Geofabrik Downloads"
+           description: "Regularly-updated extracts of continents, countries, and selected cities"
+         metro:
+           title: "Metro Extracts"
+           description: "Extracts for major world cities and their surrounding areas"
+         other:
+           title: "Other Sources"
+           description: "Additional sources listed on the OpenStreetMap wiki"
+       options: "Options"
+       format: "Format"
+       scale: "Scale"
+       max: "max"
+       image_size: "Image Size"
+       zoom: "Zoom"
+       add_marker: "Add a marker to the map"
+       latitude: "Lat:"
+       longitude: "Lon:"
+       output: "Output"
+       paste_html: "Paste HTML to embed in website"
+       export_button: "Export"
+     fixthemap:
+       title: Report a problem / Fix the map
+       how_to_help:
+         title: How to Help
+         join_the_community:
+           title: Join the community
+           explanation_html: |
+             If you have noticed a problem with our map data, for example a road is missing or your address, the best way to
+             proceed is to join the OpenStreetMap community and add or repair the data yourself.
+         add_a_note:
+           instructions_html: |
+             Just click <a class='icon note'></a> or the same icon on the map display.
+             This will add a marker to the map, which you can move
+             by dragging. Add your message, then click save, and other mappers will investigate.
+       other_concerns:
+         title: Other concerns
+         explanation_html: |
+           If you have concerns about how our data is being used or about the contents please consult our
+           <a href='/copyright'>copyright page</a> for more legal information, or contact the appropriate
+           <a href='https://wiki.osmfoundation.org/wiki/Working_Groups'>OSMF working group</a>.
+     help:
+       title: Getting Help
+       introduction: |
+         OpenStreetMap has several resources for learning about the project, asking and answering questions,
+         and collaboratively discussing and documenting mapping topics.
+       welcome:
+         url: /welcome
+         title: Welcome to OSM
+         description: Start with this quick guide covering the OpenStreetMap basics.
+       beginners_guide:
+         url: https://wiki.openstreetmap.org/wiki/Beginners%27_guide
+         title: Beginners' Guide
+         description: Community maintained guide for beginners.
+       help:
+         url: https://help.openstreetmap.org/
+         title: help.openstreetmap.org
+         description: Ask a question or look up answers on OSM's question-and-answer site.
+       mailing_lists:
+         url: https://lists.openstreetmap.org/
+         title: Mailing Lists
+         description: Ask a question or discuss interesting matters on a wide range of topical or regional mailing lists.
+       forums:
+         url: https://forum.openstreetmap.org/
+         title: Forums
+         description: Questions and discussions for those that prefer a bulletin board style interface.
+       irc:
+         url: https://irc.openstreetmap.org/
+         title: IRC
+         description: Interactive chat in many different languages and on many topics.
+       switch2osm:
+         url: https://switch2osm.org/
+         title: switch2osm
+         description: Help for companies and organisations switching to OpenStreetMap based maps and other services.
+       wiki:
+         url: https://wiki.openstreetmap.org/
+         title: wiki.openstreetmap.org
+         description: Browse the wiki for in-depth OSM documentation.
      sidebar:
        search_results: Search Results
        close: Close
        image: Image
        alt: Alt text
        url: URL
-   trace:
+     welcome:
+       title: Welcome!
+       introduction_html: |
+         Welcome to OpenStreetMap, the free and editable map of the world. Now that you're signed
+         up, you're all set to get started mapping. Here's a quick guide with the most important
+         things you need to know.
+       whats_on_the_map:
+         title: What's on the Map
+         on_html: |
+           OpenStreetMap is a place for mapping things that are both <em>real and current</em> -
+           it includes millions of buildings, roads, and other details about places. You can map
+           whatever real-world features are interesting to you.
+         off_html: |
+           What it <em>doesn't</em> include is opinionated data like ratings, historical or
+           hypothetical features, and data from copyrighted sources. Unless you have special
+           permission, don't copy from online or paper maps.
+       basic_terms:
+         title: Basic Terms For Mapping
+         paragraph_1_html: |
+           OpenStreetMap has some of its own lingo. Here are a few key words that'll come in handy.
+         editor_html: |
+           An <strong>editor</strong> is a program or website you can use to edit the map.
+         node_html: |
+           A <strong>node</strong> is a point on the map, like a single restaurant or a tree.
+         way_html: |
+           A <strong>way</strong> is a line or area, like a road, stream, lake or building.
+         tag_html: |
+           A <strong>tag</strong> is a bit of data about a node or way, like a
+           restaurant's name or a road's speed limit.
+       rules:
+         title: Rules!
+         paragraph_1_html: |
+           OpenStreetMap has few formal rules but we expect all participants to collaborate
+           with, and communicate with, the community. If you are considering
+           any activities other than editing by hand, please read and follow the guidelines on
+           <a href='https://wiki.openstreetmap.org/wiki/Import/Guidelines'>Imports</a> and
+           <a href='https://wiki.openstreetmap.org/wiki/Automated_Edits_code_of_conduct'>Automated Edits</a>.
+       questions:
+         title: Any questions?
+         paragraph_1_html: |
+           OpenStreetMap has several resources for learning about the project, asking and answering
+           questions, and collaboratively discussing and documenting mapping topics.
+           <a href='%{help_url}'>Get help here</a>.
+       start_mapping: Start Mapping
+       add_a_note:
+         title: No Time To Edit? Add a Note!
+         paragraph_1_html: |
+           If you just want something small fixed and don't have the time to sign up and learn how to edit, it's
+           easy to add a note.
+         paragraph_2_html: |
+           Just go to <a href='%{map_url}'>the map</a> and click the note icon:
+           <span class='icon note'></span>. This will add a marker to the map, which you can move
+           by dragging. Add your message, then click save, and other mappers will investigate.
+   traces:
      visibility:
        private: "Private (only shared as anonymous, unordered points)"
        public: "Public (shown in trace list and as anonymous, unordered points)"
        trackable: "Trackable (only shared as anonymous, ordered points with timestamps)"
        identifiable: "Identifiable (shown in trace list and as identifiable, ordered points with timestamps)"
+     new:
+       upload_trace: "Upload GPS Trace"
+       upload_gpx: "Upload GPX File:"
+       description: "Description:"
+       tags: "Tags:"
+       tags_help: "comma delimited"
+       visibility: "Visibility:"
+       visibility_help: "what does this mean?"
+       visibility_help_url: "https://wiki.openstreetmap.org/wiki/Visibility_of_GPS_traces"
+       upload_button: "Upload"
+       help: "Help"
+       help_url: "https://wiki.openstreetmap.org/wiki/Upload"
      create:
        upload_trace: "Upload GPS Trace"
        trace_uploaded: "Your GPX file has been uploaded and is awaiting insertion in to the database. This will usually happen within half an hour, and an email will be sent to you on completion."
+       traces_waiting:
+         one: "You have %{count} trace waiting for upload. Please consider waiting for these to finish before uploading any more, so as not to block the queue for other users."
+         other: "You have %{count} traces waiting for upload. Please consider waiting for these to finish before uploading any more, so as not to block the queue for other users."
      edit:
        title: "Editing trace %{name}"
        heading: "Editing trace %{name}"
        visibility: "Visibility:"
        visibility_help: "what does this mean?"
        visibility_help_url: "https://wiki.openstreetmap.org/wiki/Visibility_of_GPS_traces"
-     trace_form:
-       upload_gpx: "Upload GPX File:"
-       description: "Description:"
-       tags: "Tags:"
-       tags_help: "comma delimited"
-       visibility: "Visibility:"
-       visibility_help: "what does this mean?"
-       visibility_help_url: "https://wiki.openstreetmap.org/wiki/Visibility_of_GPS_traces"
-       upload_button: "Upload"
-       help: "Help"
-       help_url: "https://wiki.openstreetmap.org/wiki/Upload"
-     trace_header:
-       upload_trace: "Upload a trace"
-       see_all_traces: "See all traces"
-       see_my_traces: "See my traces"
-       traces_waiting:
-         one: "You have %{count} trace waiting for upload. Please consider waiting for these to finish before uploading any more, so as not to block the queue for other users."
-         other: "You have %{count} traces waiting for upload. Please consider waiting for these to finish before uploading any more, so as not to block the queue for other users."
      trace_optionals:
        tags: "Tags"
      view:
        description: "Browse recent GPS trace uploads"
        tagged_with: " tagged with %{tags}"
        empty_html: "Nothing here yet. <a href='%{upload_link}'>Upload a new trace</a> or learn more about GPS tracing on the <a href='https://wiki.openstreetmap.org/wiki/Beginners_Guide_1.2'>wiki page</a>."
+       upload_trace: "Upload a trace"
+       see_all_traces: "See all traces"
+       see_my_traces: "See my traces"
      delete:
        scheduled_for_deletion: "Trace scheduled for deletion"
      make_public:
    application:
      require_cookies:
        cookies_needed: "You appear to have cookies disabled - please enable cookies in your browser before continuing."
 +    require_admin:
 +      not_an_admin: You need to be an admin to perform that action.
      require_moderator:
        not_a_moderator: "You need to be a moderator to perform that action."
 +    require_moderator_or_admin:
 +      not_a_moderator_or_admin: You need to be a moderator or an admin to perform that action
      setup_user_auth:
        blocked_zero_hour: "You have an urgent message on the OpenStreetMap web site. You need to read the message before you will be able to save your edits."
        blocked: "Your access to the API has been blocked. Please log-in to the web interface to find out more."
        need_to_see_terms: "Your access to the API is temporarily suspended. Please log-in to the web interface to view the Contributor Terms. You do not need to agree, but you must view them."
    oauth:
-     oauthorize:
+     authorize:
        title: "Authorize access to your account"
        request_access: "The application %{app_name} is requesting access to your account, %{user}. Please check whether you would like the application to have the following capabilities. You may choose as many or as few as you like."
        allow_to: "Allow the client application to:"
        allow_write_gpx:   "upload GPS traces."
        allow_write_notes: "modify notes."
        grant_access: "Grant Access"
-     oauthorize_success:
+     authorize_success:
        title: "Authorization request allowed"
        allowed: "You have granted application %{app_name} access to your account."
        verification: "The verification code is %{code}."
-     oauthorize_failure:
+     authorize_failure:
        title: "Authorization request failed"
        denied: "You have denied application %{app_name} access to your account."
        invalid: "The authorization token is not valid."
        friends_diaries: "friends' diary entries"
        nearby_changesets: "nearby user changesets"
        nearby_diaries: "nearby user diary entries"
 +      report: Report this User
      popup:
        your location: "Your location"
        nearby mapper: "Nearby mapper"
        are_you_sure: "Are you sure you want to revoke the role `%{role}' from the user `%{name}'?"
        confirm: "Confirm"
        fail: "Could not revoke role `%{role}' from user `%{name}'. Please check that the user and role are both valid."
-   user_block:
+   user_blocks:
      model:
        non_moderator_update: "Must be a moderator to create or update a block."
        non_moderator_revoke: "Must be a moderator to revoke a block."
      period:
        one: "1 hour"
        other: "%{count} hours"
-     partial:
-       show: "Show"
-       edit: "Edit"
-       revoke: "Revoke!"
-       confirm: "Are you sure?"
-       display_name: "Blocked User"
-       creator_name: "Creator"
-       reason: "Reason for block"
-       status: "Status"
-       revoker_name: "Revoked by"
-       not_revoked: "(not revoked)"
-       showing_page: "Page %{page}"
-       next: "Next Â»"
-       previous: "« Previous"
      helper:
        time_future: "Ends in %{time}."
        until_login: "Active until the user logs in."
        back: "View all blocks"
        revoker: "Revoker:"
        needs_view: "The user needs to log in before this block will be cleared."
-   note:
-     description:
+     block:
+       not_revoked: "(not revoked)"
+       show: "Show"
+       edit: "Edit"
+       revoke: "Revoke!"
+     blocks:
+       display_name: "Blocked User"
+       creator_name: "Creator"
+       reason: "Reason for block"
+       status: "Status"
+       revoker_name: "Revoked by"
+       showing_page: "Page %{page}"
+       next: "Next Â»"
+       previous: "« Previous"
+   notes:
+     comment:
        opened_at_html: "Created %{when} ago"
        opened_at_by_html: "Created %{when} ago by %{user}"
        commented_at_html: "Updated %{when} ago"
          against_oneway_without_exit: Go against one-way on %{name}
          end_oneway_without_exit: End of one-way on %{name}
          roundabout_with_exit: At roundabout take exit %{exit} onto %{name}
-         turn_left_with_exit: At roundabout turn left onto %{name}
-         slight_left_with_exit: At roundabout slight left onto %{name}
-         turn_right_with_exit: At roundabout turn right onto %{name}
-         slight_right_with_exit: At roundabout slight right onto %{name}
-         continue_with_exit: At roundabout continue straight onto %{name}
+         roundabout_with_exit_ordinal: At roundabout take %{exit} exit onto %{name}
+         exit_roundabout: Exit roundabout onto %{name}
          unnamed: "unnamed road"
          courtesy: "Directions courtesy of %{link}"
+         exit_counts:
+           first: "1st"
+           second: "2nd"
+           third: "3rd"
+           fourth: "4th"
+           fifth: "5th"
+           sixth: "6th"
+           seventh: "7th"
+           eighth: "8th"
+           ninth: "9th"
+           tenth: "10th"
        time: "Time"
      query:
        node: Node
        show_address: Show address
        query_features: Query features
        centre_map: Centre map here
-   redaction:
+   redactions:
      edit:
        description: "Description"
        heading: "Edit redaction"
diff --combined config/routes.rb
index 0c250b0cc34691d937b5b576e77b30d5b1f209aa,741268e4623ee6202d6791d58e682ef729f72fa7..16ba85754f3684b6ea7c5835b48694b4d4568832
@@@ -68,18 -68,18 +68,18 @@@ OpenStreetMap::Application.routes.draw 
      get "user/details" => "user#api_details"
      get "user/gpx_files" => "user#api_gpx_files"
  
-     get "user/preferences" => "user_preference#read"
-     get "user/preferences/:preference_key" => "user_preference#read_one"
-     put "user/preferences" => "user_preference#update"
-     put "user/preferences/:preference_key" => "user_preference#update_one"
-     delete "user/preferences/:preference_key" => "user_preference#delete_one"
-     post "gpx/create" => "trace#api_create"
-     get "gpx/:id" => "trace#api_read", :id => /\d+/
-     put "gpx/:id" => "trace#api_update", :id => /\d+/
-     delete "gpx/:id" => "trace#api_delete", :id => /\d+/
-     get "gpx/:id/details" => "trace#api_read", :id => /\d+/
-     get "gpx/:id/data" => "trace#api_data"
+     get "user/preferences" => "user_preferences#read"
+     get "user/preferences/:preference_key" => "user_preferences#read_one"
+     put "user/preferences" => "user_preferences#update"
+     put "user/preferences/:preference_key" => "user_preferences#update_one"
+     delete "user/preferences/:preference_key" => "user_preferences#delete_one"
+     post "gpx/create" => "traces#api_create"
+     get "gpx/:id" => "traces#api_read", :id => /\d+/
+     put "gpx/:id" => "traces#api_update", :id => /\d+/
+     delete "gpx/:id" => "traces#api_delete", :id => /\d+/
+     get "gpx/:id/details" => "traces#api_read", :id => /\d+/
+     get "gpx/:id/data" => "traces#api_data"
  
      # AMF (ActionScript) API
      post "amf/read" => "amf#amf_read"
    post "/preview/:type" => "site#preview", :as => :preview
  
    # traces
-   get "/user/:display_name/traces/tag/:tag/page/:page" => "trace#list", :page => /[1-9][0-9]*/
-   get "/user/:display_name/traces/tag/:tag" => "trace#list"
-   get "/user/:display_name/traces/page/:page" => "trace#list", :page => /[1-9][0-9]*/
-   get "/user/:display_name/traces" => "trace#list"
-   get "/user/:display_name/traces/tag/:tag/rss" => "trace#georss", :defaults => { :format => :rss }
-   get "/user/:display_name/traces/rss" => "trace#georss", :defaults => { :format => :rss }
-   get "/user/:display_name/traces/:id" => "trace#view"
-   get "/user/:display_name/traces/:id/picture" => "trace#picture"
-   get "/user/:display_name/traces/:id/icon" => "trace#icon"
-   get "/traces/tag/:tag/page/:page" => "trace#list", :page => /[1-9][0-9]*/
-   get "/traces/tag/:tag" => "trace#list"
-   get "/traces/page/:page" => "trace#list", :page => /[1-9][0-9]*/
-   get "/traces" => "trace#list"
-   get "/traces/tag/:tag/rss" => "trace#georss", :defaults => { :format => :rss }
-   get "/traces/rss" => "trace#georss", :defaults => { :format => :rss }
-   get "/traces/mine/tag/:tag/page/:page" => "trace#mine", :page => /[1-9][0-9]*/
-   get "/traces/mine/tag/:tag" => "trace#mine"
-   get "/traces/mine/page/:page" => "trace#mine"
-   get "/traces/mine" => "trace#mine"
-   match "/trace/create" => "trace#create", :via => [:get, :post]
-   get "/trace/:id/data" => "trace#data", :id => /\d+/, :as => "trace_data"
-   match "/trace/:id/edit" => "trace#edit", :via => [:get, :post], :id => /\d+/, :as => "trace_edit"
-   post "/trace/:id/delete" => "trace#delete", :id => /\d+/
+   get "/user/:display_name/traces/tag/:tag/page/:page" => "traces#list", :page => /[1-9][0-9]*/
+   get "/user/:display_name/traces/tag/:tag" => "traces#list"
+   get "/user/:display_name/traces/page/:page" => "traces#list", :page => /[1-9][0-9]*/
+   get "/user/:display_name/traces" => "traces#list"
+   get "/user/:display_name/traces/tag/:tag/rss" => "traces#georss", :defaults => { :format => :rss }
+   get "/user/:display_name/traces/rss" => "traces#georss", :defaults => { :format => :rss }
+   get "/user/:display_name/traces/:id" => "traces#view"
+   get "/user/:display_name/traces/:id/picture" => "traces#picture"
+   get "/user/:display_name/traces/:id/icon" => "traces#icon"
+   get "/traces/tag/:tag/page/:page" => "traces#list", :page => /[1-9][0-9]*/
+   get "/traces/tag/:tag" => "traces#list"
+   get "/traces/page/:page" => "traces#list", :page => /[1-9][0-9]*/
+   get "/traces" => "traces#list"
+   get "/traces/tag/:tag/rss" => "traces#georss", :defaults => { :format => :rss }
+   get "/traces/rss" => "traces#georss", :defaults => { :format => :rss }
+   get "/traces/mine/tag/:tag/page/:page" => "traces#mine", :page => /[1-9][0-9]*/
+   get "/traces/mine/tag/:tag" => "traces#mine"
+   get "/traces/mine/page/:page" => "traces#mine"
+   get "/traces/mine" => "traces#mine"
+   resources :traces, :only => [:new, :create]
+   post "/trace/create" => "traces#create" # remove after deployment
+   get "/trace/create", :to => redirect(:path => "/traces/new")
+   get "/trace/:id/data" => "traces#data", :id => /\d+/, :as => "trace_data"
+   match "/trace/:id/edit" => "traces#edit", :via => [:get, :post], :id => /\d+/, :as => "trace_edit"
+   post "/trace/:id/delete" => "traces#delete", :id => /\d+/
  
    # diary pages
    match "/diary/new" => "diary_entry#new", :via => [:get, :post]
    get "/export/embed" => "export#embed"
  
    # messages
-   get "/user/:display_name/inbox" => "message#inbox", :as => "inbox"
-   get "/user/:display_name/outbox" => "message#outbox", :as => "outbox"
-   match "/message/new/:display_name" => "message#new", :via => [:get, :post], :as => "new_message"
-   get "/message/read/:message_id" => "message#read", :as => "read_message"
-   post "/message/mark/:message_id" => "message#mark", :as => "mark_message"
-   match "/message/reply/:message_id" => "message#reply", :via => [:get, :post], :as => "reply_message"
-   post "/message/delete/:message_id" => "message#delete", :as => "delete_message"
+   resources :messages, :only => [:show] do
+     collection do
+       get :inbox
+       get :outbox
+     end
+   end
+   get "/user/:display_name/inbox", :to => redirect(:path => "/messages/inbox")
+   get "/user/:display_name/outbox", :to => redirect(:path => "/messages/outbox")
+   match "/message/new/:display_name" => "messages#new", :via => [:get, :post], :as => "new_message"
+   get "/message/read/:message_id", :to => redirect(:path => "/messages/%{message_id}")
+   post "/message/mark/:message_id" => "messages#mark", :as => "mark_message"
+   match "/message/reply/:message_id" => "messages#reply", :via => [:get, :post], :as => "reply_message"
+   post "/message/delete/:message_id" => "messages#destroy", :as => "destroy_message"
  
    # oauth admin pages (i.e: for setting up new clients, etc...)
    scope "/user/:display_name" do
    resources :user_blocks
    match "/blocks/:id/revoke" => "user_blocks#revoke", :via => [:get, :post], :as => "revoke_user_block"
  
 +  # issues and reports
 +  resources :issues do
 +    resources :comments, :controller => :issue_comments
 +    member do
 +      post "resolve"
 +      post "assign"
 +      post "ignore"
 +      post "reopen"
 +    end
 +  end
 +
 +  resources :reports
 +
    # redactions
    resources :redactions
  end
index 8804b6b2861d79ed4be2d04c2ce545795d7a120f,0000000000000000000000000000000000000000..25721295302e28ebdb74e3e1e916ba9b7cc92a8b
mode 100644,000000..100644
--- /dev/null
@@@ -1,58 -1,0 +1,58 @@@
-     assert !issue.valid?
 +require "test_helper"
 +
 +class IssueTest < ActiveSupport::TestCase
 +  def test_assigned_role
 +    issue = create(:issue)
 +
 +    assert issue.valid?
 +    issue.assigned_role = "bogus"
++    assert_not issue.valid?
 +  end
 +
 +  def test_reported_user
 +    note = create(:note_comment, :author => create(:user)).note
 +    anonymous_note = create(:note_comment, :author => nil).note
 +    user = create(:user)
 +    create(:language, :code => "en")
 +    diary_entry = create(:diary_entry)
 +    issue = Issue.new
 +
 +    issue.reportable = user
 +    issue.save!
 +    assert_equal issue.reported_user, user
 +
 +    issue.reportable = note
 +    issue.save!
 +    assert_equal issue.reported_user, note.author
 +
 +    issue.reportable = anonymous_note
 +    issue.save!
 +    assert_nil issue.reported_user
 +
 +    issue.reportable = diary_entry
 +    issue.save!
 +    assert_equal issue.reported_user, diary_entry.user
 +  end
 +
 +  def test_default_assigned_role
 +    create(:language, :code => "en")
 +    diary_entry = create(:diary_entry)
 +    note = create(:note_with_comments)
 +
 +    issue = Issue.new
 +    issue.reportable = diary_entry
 +    issue.save!
 +    assert_equal "administrator", issue.assigned_role
 +
 +    issue = Issue.new
 +    issue.reportable = note
 +    issue.save!
 +    assert_equal "moderator", issue.assigned_role
 +
 +    # check the callback doesn't override an explicitly set role
 +    issue.assigned_role = "administrator"
 +    issue.save!
 +    issue.reload
 +    assert_equal "administrator", issue.assigned_role
 +  end
 +end
index 810035c9da5d9a3fbdd97d986ad189fb377c37b9,0000000000000000000000000000000000000000..b65753b822d4e1a075d5337d37d951457990a648
mode 100644,000000..100644
--- /dev/null
@@@ -1,35 -1,0 +1,35 @@@
-     assert !report.valid?
 +require "test_helper"
 +
 +class ReportTest < ActiveSupport::TestCase
 +  def test_issue_required
 +    report = create(:report)
 +
 +    assert report.valid?
 +    report.issue = nil
-     assert !report.valid?
++    assert_not report.valid?
 +  end
 +
 +  def test_user_required
 +    report = create(:report)
 +
 +    assert report.valid?
 +    report.user = nil
-     assert !report.valid?
++    assert_not report.valid?
 +  end
 +
 +  def test_details_required
 +    report = create(:report)
 +
 +    assert report.valid?
 +    report.details = ""
-     assert !report.valid?
++    assert_not report.valid?
 +  end
 +
 +  def test_category_required
 +    report = create(:report)
 +
 +    assert report.valid?
 +    report.category = ""
++    assert_not report.valid?
 +  end
 +end
index 5e60ee0f0c6f6b5448c43ee562cd5534b2fe7040,0000000000000000000000000000000000000000..b77908f076dbf2fbf5f0fe03ce121bb7e63b4175
mode 100644,000000..100644
--- /dev/null
@@@ -1,116 -1,0 +1,116 @@@
-     assert !page.has_content?(I18n.t("issues.index.issues_not_found"))
 +require "application_system_test_case"
 +
 +class IssuesTest < ApplicationSystemTestCase
 +  include IssuesHelper
 +
 +  def test_view_issues_not_logged_in
 +    visit issues_path
 +    assert page.has_content?(I18n.t("user.login.title"))
 +  end
 +
 +  def test_view_issues_normal_user
 +    sign_in_as(create(:user))
 +
 +    visit issues_path
 +    assert page.has_content?(I18n.t("application.require_moderator_or_admin.not_a_moderator_or_admin"))
 +  end
 +
 +  def test_view_no_issues
 +    sign_in_as(create(:moderator_user))
 +
 +    visit issues_path
 +    assert page.has_content?(I18n.t("issues.index.issues_not_found"))
 +  end
 +
 +  def test_view_issues
 +    sign_in_as(create(:moderator_user))
 +    issues = create_list(:issue, 3, :assigned_role => "moderator")
 +
 +    visit issues_path
 +    assert page.has_content?(issues.first.reported_user.display_name)
 +  end
 +
 +  def test_view_issues_with_no_reported_user
 +    sign_in_as(create(:moderator_user))
 +    anonymous_note = create(:note_with_comments)
 +    issue = create(:issue, :reportable => anonymous_note)
 +
 +    visit issues_path
 +    assert page.has_content?(reportable_title(anonymous_note))
 +
 +    visit issue_path(issue)
 +    assert page.has_content?(reportable_title(anonymous_note))
 +  end
 +
 +  def test_search_issues_by_user
 +    good_user = create(:user)
 +    bad_user = create(:user)
 +    create(:issue, :reportable => bad_user, :reported_user => bad_user, :assigned_role => "administrator")
 +
 +    sign_in_as(create(:administrator_user))
 +
 +    # No issues against the user
 +    visit issues_path
 +    fill_in "search_by_user", :with => good_user.display_name
 +    click_on "Search"
 +    assert page.has_content?(I18n.t("issues.index.issues_not_found"))
 +
 +    # User doesn't exist
 +    visit issues_path
 +    fill_in "search_by_user", :with => "Nonexistant User"
 +    click_on "Search"
 +    assert page.has_content?(I18n.t("issues.index.user_not_found"))
 +
 +    # Find Issue against bad_user
 +    visit issues_path
 +    fill_in "search_by_user", :with => bad_user.display_name
 +    click_on "Search"
++    assert_not page.has_content?(I18n.t("issues.index.issues_not_found"))
 +  end
 +
 +  def test_commenting
 +    issue = create(:issue)
 +    sign_in_as(create(:moderator_user))
 +
 +    visit issue_path(issue)
 +
 +    fill_in :issue_comment_body, :with => "test comment"
 +    click_on "Submit"
 +    assert page.has_content?(I18n.t("issue_comments.create.comment_created"))
 +    assert page.has_content?("test comment")
 +
 +    issue.reload
 +    assert_equal issue.comments.first.body, "test comment"
 +  end
 +
 +  def test_reassign_issue
 +    issue = create(:issue)
 +    assert_equal "administrator", issue.assigned_role
 +    sign_in_as(create(:administrator_user))
 +
 +    visit issue_path(issue)
 +
 +    fill_in :issue_comment_body, :with => "reassigning to moderators"
 +    check :reassign
 +    click_on "Submit"
 +
 +    issue.reload
 +    assert_equal "moderator", issue.assigned_role
 +  end
 +
 +  def test_issue_index_with_multiple_roles
 +    user1 = create(:user)
 +    user2 = create(:user)
 +    issue1 = create(:issue, :reportable => user1, :assigned_role => "administrator")
 +    issue2 = create(:issue, :reportable => user2, :assigned_role => "moderator")
 +
 +    user = create(:administrator_user)
 +    create(:user_role, :user => user, :role => "moderator")
 +    sign_in_as(user)
 +
 +    visit issues_path
 +
 +    assert page.has_link?(I18n.t("issues.index.reports_count", :count => issue1.reports_count), :href => issue_path(issue1))
 +    assert page.has_link?(I18n.t("issues.index.reports_count", :count => issue2.reports_count), :href => issue_path(issue2))
 +  end
 +end
index 05b76f695aeb6eaf230397b69567cf83b8d288f7,0000000000000000000000000000000000000000..852bcfa65d6d3a7fece6d822db7d8a8e571c6fd3
mode 100644,000000..100644
--- /dev/null
@@@ -1,35 -1,0 +1,35 @@@
-     assert !page.has_content?(I18n.t("diary_entry.diary_comment.report"))
 +require "application_system_test_case"
 +
 +class ReportDiaryCommentTest < ApplicationSystemTestCase
 +  def setup
 +    create(:language, :code => "en")
 +    @diary_entry = create(:diary_entry)
 +    @comment = create(:diary_comment, :diary_entry => @diary_entry)
 +  end
 +
 +  def test_no_link_when_not_logged_in
 +    visit diary_entry_path(@diary_entry.user.display_name, @diary_entry)
 +    assert page.has_content?(@comment.body)
 +
++    assert_not page.has_content?(I18n.t("diary_entry.diary_comment.report"))
 +  end
 +
 +  def test_it_works
 +    sign_in_as(create(:user))
 +    visit diary_entry_path(@diary_entry.user.display_name, @diary_entry)
 +    assert page.has_content? @diary_entry.title
 +
 +    click_on I18n.t("diary_entry.diary_comment.report")
 +    assert page.has_content? "Report"
 +    assert page.has_content? I18n.t("reports.new.disclaimer.intro")
 +
 +    choose I18n.t("reports.new.categories.diary_comment.spam")
 +    fill_in "report_details", :with => "This comment is spam"
 +    click_on "Create Report"
 +
 +    assert page.has_content? "Your report has been registered sucessfully"
 +
 +    assert_equal 1, Issue.count
 +    assert Issue.last.reportable == @comment
 +  end
 +end
index 86d301e3c5edfca2a157e0f15a742bbdc0148fae,0000000000000000000000000000000000000000..15752777c5517f193afdcaee27a0d4fc3fa9e1d5
mode 100644,000000..100644
--- /dev/null
@@@ -1,58 -1,0 +1,58 @@@
-     assert !page.has_content?(I18n.t("diary_entry.diary_entry.report"))
 +require "application_system_test_case"
 +
 +class ReportDiaryEntryTest < ApplicationSystemTestCase
 +  def setup
 +    create(:language, :code => "en")
 +    @diary_entry = create(:diary_entry)
 +  end
 +
 +  def test_no_link_when_not_logged_in
 +    visit diary_entry_path(@diary_entry.user.display_name, @diary_entry)
 +    assert page.has_content?(@diary_entry.title)
 +
-     assert !issue.resolved?
++    assert_not page.has_content?(I18n.t("diary_entry.diary_entry.report"))
 +  end
 +
 +  def test_it_works
 +    sign_in_as(create(:user))
 +    visit diary_entry_path(@diary_entry.user.display_name, @diary_entry)
 +    assert page.has_content? @diary_entry.title
 +
 +    click_on I18n.t("diary_entry.diary_entry.report")
 +    assert page.has_content? "Report"
 +    assert page.has_content? I18n.t("reports.new.disclaimer.intro")
 +
 +    choose I18n.t("reports.new.categories.diary_entry.spam")
 +    fill_in "report_details", :with => "This is advertising"
 +    click_on "Create Report"
 +
 +    assert page.has_content? "Your report has been registered sucessfully"
 +  end
 +
 +  def test_it_reopens_issue
 +    issue = create(:issue, :reportable => @diary_entry)
 +    issue.resolve!
 +
 +    sign_in_as(create(:user))
 +    visit diary_entry_path(@diary_entry.user.display_name, @diary_entry)
 +    assert page.has_content? @diary_entry.title
 +
 +    click_on I18n.t("diary_entry.diary_entry.report")
 +    assert page.has_content? "Report"
 +    assert page.has_content? I18n.t("reports.new.disclaimer.intro")
 +
 +    choose I18n.t("reports.new.categories.diary_entry.spam")
 +    fill_in "report_details", :with => "This is advertising"
 +    click_on "Create Report"
 +
 +    issue.reload
++    assert_not issue.resolved?
 +    assert issue.open?
 +  end
 +
 +  def test_missing_report_params
 +    sign_in_as(create(:user))
 +    visit new_report_path
 +    assert page.has_content? I18n.t("reports.new.missing_params")
 +  end
 +end
index f885888349a709a3c3c63d968ecd7ddf87273e57,0000000000000000000000000000000000000000..759306e08f30dbc573782ece28576a3ab9d77f08
mode 100644,000000..100644
--- /dev/null
@@@ -1,49 -1,0 +1,49 @@@
-     assert !page.has_content?(I18n.t("browse.note.report"))
 +require "application_system_test_case"
 +
 +class ReportNoteTest < ApplicationSystemTestCase
 +  def test_no_link_when_not_logged_in
 +    note = create(:note_with_comments)
 +    visit browse_note_path(note)
 +    assert page.has_content?(note.comments.first.body)
 +
++    assert_not page.has_content?(I18n.t("browse.note.report"))
 +  end
 +
 +  def test_can_report_anonymous_notes
 +    note = create(:note_with_comments)
 +    sign_in_as(create(:user))
 +    visit browse_note_path(note)
 +
 +    click_on I18n.t("browse.note.report")
 +    assert page.has_content? "Report"
 +    assert page.has_content? I18n.t("reports.new.disclaimer.intro")
 +
 +    choose I18n.t("reports.new.categories.note.spam")
 +    fill_in "report_details", :with => "This is spam"
 +    click_on "Create Report"
 +
 +    assert page.has_content? "Your report has been registered sucessfully"
 +
 +    assert_equal 1, Issue.count
 +    assert Issue.last.reportable == note
 +  end
 +
 +  def test_can_report_notes_with_author
 +    note = create(:note_comment, :author => create(:user)).note
 +    sign_in_as(create(:user))
 +    visit browse_note_path(note)
 +
 +    click_on I18n.t("browse.note.report")
 +    assert page.has_content? "Report"
 +    assert page.has_content? I18n.t("reports.new.disclaimer.intro")
 +
 +    choose I18n.t("reports.new.categories.note.spam")
 +    fill_in "report_details", :with => "This is spam"
 +    click_on "Create Report"
 +
 +    assert page.has_content? "Your report has been registered sucessfully"
 +
 +    assert_equal 1, Issue.count
 +    assert Issue.last.reportable == note
 +  end
 +end
index 0331e3ad73a936d50c9dbf5690b0a4b81a20abea,0000000000000000000000000000000000000000..8bb7d9dd7ed397284faa97ee1952ebecfc0f6c68
mode 100644,000000..100644
--- /dev/null
@@@ -1,30 -1,0 +1,30 @@@
-     assert !page.has_content?(I18n.t("user.view.report"))
 +require "application_system_test_case"
 +
 +class ReportUserTest < ApplicationSystemTestCase
 +  def test_no_link_when_not_logged_in
 +    note = create(:note_with_comments)
 +    visit browse_note_path(note)
 +    assert page.has_content?(note.comments.first.body)
 +
++    assert_not page.has_content?(I18n.t("user.view.report"))
 +  end
 +
 +  def test_can_report_user
 +    user = create(:user)
 +    sign_in_as(create(:user))
 +    visit user_path(user.display_name)
 +
 +    click_on I18n.t("user.view.report")
 +    assert page.has_content? "Report"
 +    assert page.has_content? I18n.t("reports.new.disclaimer.intro")
 +
 +    choose I18n.t("reports.new.categories.user.vandal")
 +    fill_in "report_details", :with => "This user is a vandal"
 +    click_on "Create Report"
 +
 +    assert page.has_content? "Your report has been registered sucessfully"
 +
 +    assert_equal 1, Issue.count
 +    assert Issue.last.reportable == user
 +  end
 +end