]> git.openstreetmap.org Git - rails.git/commitdiff
Merge pull request #5019 from tomhughes/oauth2-cleanup
authorAndy Allan <git@gravitystorm.co.uk>
Wed, 7 Aug 2024 15:22:21 +0000 (16:22 +0100)
committerGitHub <noreply@github.com>
Wed, 7 Aug 2024 15:22:21 +0000 (16:22 +0100)
Add expiry for OAuth 2 grants and tokens

121 files changed:
.rubocop_todo.yml
Gemfile.lock
app/abilities/api_capability.rb
app/assets/javascripts/richtext.js
app/controllers/api/messages_controller.rb [new file with mode: 0644]
app/controllers/diary_entries_controller.rb
app/controllers/site_controller.rb
app/controllers/user_blocks_controller.rb
app/helpers/open_graph_helper.rb
app/helpers/trace_helper.rb
app/views/api/changesets/index.json.jbuilder
app/views/api/changesets/index.xml.builder
app/views/api/messages/_message.json.jbuilder [new file with mode: 0644]
app/views/api/messages/_message.xml.builder [new file with mode: 0644]
app/views/api/messages/inbox.json.jbuilder [new file with mode: 0644]
app/views/api/messages/inbox.xml.builder [new file with mode: 0644]
app/views/api/messages/outbox.json.jbuilder [new file with mode: 0644]
app/views/api/messages/outbox.xml.builder [new file with mode: 0644]
app/views/api/messages/show.json.jbuilder [new file with mode: 0644]
app/views/api/messages/show.xml.builder [new file with mode: 0644]
app/views/api/notes/index.json.jbuilder
app/views/api/users/index.json.jbuilder
app/views/layouts/_header.html.erb
app/views/layouts/_meta.html.erb
app/views/shared/_richtext_field.html.erb
app/views/traces/_trace.html.erb
app/views/traces/edit.html.erb
app/views/traces/show.html.erb
app/views/user_blocks/_block.html.erb
app/views/user_blocks/show.html.erb
app/views/user_mailer/_gpx_description.text.erb [new file with mode: 0644]
app/views/user_mailer/gpx_failure.text.erb [new file with mode: 0644]
app/views/user_mailer/gpx_success.text.erb [new file with mode: 0644]
config/locales/aln.yml
config/locales/ar.yml
config/locales/arz.yml
config/locales/ast.yml
config/locales/be-Tarask.yml
config/locales/be.yml
config/locales/bg.yml
config/locales/br.yml
config/locales/bs.yml
config/locales/ca.yml
config/locales/ce.yml
config/locales/cs.yml
config/locales/cy.yml
config/locales/da.yml
config/locales/de.yml
config/locales/dsb.yml
config/locales/el.yml
config/locales/en-GB.yml
config/locales/en.yml
config/locales/eo.yml
config/locales/es.yml
config/locales/et.yml
config/locales/eu.yml
config/locales/fa.yml
config/locales/fi.yml
config/locales/fr.yml
config/locales/fy.yml
config/locales/gd.yml
config/locales/gl.yml
config/locales/gu.yml
config/locales/he.yml
config/locales/hr.yml
config/locales/hsb.yml
config/locales/hu.yml
config/locales/ia.yml
config/locales/id.yml
config/locales/is.yml
config/locales/it.yml
config/locales/ja.yml
config/locales/ko.yml
config/locales/ku-Latn.yml
config/locales/lt.yml
config/locales/lv.yml
config/locales/mk.yml
config/locales/ms.yml
config/locales/nb.yml
config/locales/nl.yml
config/locales/nn.yml
config/locales/oc.yml
config/locales/pl.yml
config/locales/pt-PT.yml
config/locales/pt.yml
config/locales/ro.yml
config/locales/ru.yml
config/locales/sc.yml
config/locales/scn.yml
config/locales/sk.yml
config/locales/sl.yml
config/locales/sr-Latn.yml
config/locales/sr.yml
config/locales/sv.yml
config/locales/te.yml
config/locales/th.yml
config/locales/tl.yml
config/locales/tr.yml
config/locales/uk.yml
config/locales/vi.yml
config/locales/zh-CN.yml
config/locales/zh-TW.yml
config/routes.rb
config/settings.yml
lib/oauth.rb
lib/rich_text.rb
test/abilities/api_capability_test.rb
test/controllers/api/changeset_comments_controller_test.rb
test/controllers/api/changesets_controller_test.rb
test/controllers/api/messages_controller_test.rb [new file with mode: 0644]
test/controllers/api/nodes_controller_test.rb
test/controllers/api/relations_controller_test.rb
test/controllers/api/user_preferences_controller_test.rb
test/controllers/diary_entries_controller_test.rb
test/controllers/issues_controller_test.rb
test/controllers/user_blocks_controller_test.rb
test/factories/oauth_access_token.rb
test/lib/rich_text_test.rb
test/mailers/user_mailer_test.rb
test/models/user_test.rb
yarn.lock

index 6fe5b2e57a222f91f042f6ee05ded916b027ee11..3b18f72460c1b652651d8a0f9a3e44972cc33778 100644 (file)
@@ -71,7 +71,7 @@ Metrics/ClassLength:
 # Offense count: 59
 # Configuration parameters: AllowedMethods, AllowedPatterns.
 Metrics/CyclomaticComplexity:
-  Max: 29
+  Max: 31
 
 # Offense count: 753
 # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
@@ -86,7 +86,7 @@ Metrics/ParameterLists:
 # Offense count: 56
 # Configuration parameters: AllowedMethods, AllowedPatterns.
 Metrics/PerceivedComplexity:
-  Max: 30
+  Max: 32
 
 # Offense count: 2394
 # This cop supports safe autocorrection (--autocorrect).
@@ -95,7 +95,7 @@ Minitest/EmptyLineBeforeAssertionMethods:
 
 # Offense count: 565
 Minitest/MultipleAssertions:
-  Max: 54
+  Max: 60
 
 # Offense count: 1
 # This cop supports unsafe autocorrection (--autocorrect-all).
index 05ccd47d1f39fdde4c03cf59d7371385251f4c9d..00984911cba78e05b9f568389776d9b6d2e2f30c 100644 (file)
@@ -92,11 +92,11 @@ GEM
       ffi (~> 1.15)
       ffi-compiler (~> 1.0)
     ast (2.4.2)
-    autoprefixer-rails (10.4.16.0)
+    autoprefixer-rails (10.4.19.0)
       execjs (~> 2)
     aws-eventstream (1.3.0)
-    aws-partitions (1.957.0)
-    aws-sdk-core (3.201.2)
+    aws-partitions (1.962.0)
+    aws-sdk-core (3.201.3)
       aws-eventstream (~> 1, >= 1.3.0)
       aws-partitions (~> 1, >= 1.651.0)
       aws-sigv4 (~> 1.8)
@@ -104,11 +104,11 @@ GEM
     aws-sdk-kms (1.88.0)
       aws-sdk-core (~> 3, >= 3.201.0)
       aws-sigv4 (~> 1.5)
-    aws-sdk-s3 (1.156.0)
+    aws-sdk-s3 (1.157.0)
       aws-sdk-core (~> 3, >= 3.201.0)
       aws-sdk-kms (~> 1)
       aws-sigv4 (~> 1.5)
-    aws-sigv4 (1.8.0)
+    aws-sigv4 (1.9.1)
       aws-eventstream (~> 1, >= 1.0.2)
     base64 (0.2.0)
     better_errors (2.10.1)
@@ -125,7 +125,7 @@ GEM
     bigdecimal (3.1.8)
     binding_of_caller (1.0.1)
       debug_inspector (>= 1.2.0)
-    bootsnap (1.18.3)
+    bootsnap (1.18.4)
       msgpack (~> 1.2)
     bootstrap (5.3.3)
       autoprefixer-rails (>= 9.1.0)
@@ -177,7 +177,7 @@ GEM
     delayed_job_active_record (4.1.8)
       activerecord (>= 3.0, < 8.0)
       delayed_job (>= 3.0, < 5)
-    docile (1.4.0)
+    docile (1.4.1)
     doorkeeper (5.7.1)
       railties (>= 5)
     doorkeeper-i18n (5.2.7)
@@ -219,12 +219,12 @@ GEM
       dry-initializer (~> 3.0)
       dry-schema (>= 1.12, < 2)
       zeitwerk (~> 2.6)
-    erb_lint (0.5.0)
+    erb_lint (0.6.0)
       activesupport
       better_html (>= 2.0.1)
       parser (>= 2.7.1.4)
       rainbow
-      rubocop
+      rubocop (>= 1)
       smart_properties
     erubi (1.13.0)
     execjs (2.9.1)
@@ -234,10 +234,10 @@ GEM
     factory_bot_rails (6.4.3)
       factory_bot (~> 6.4)
       railties (>= 5.0.0)
-    faraday (2.10.0)
+    faraday (2.10.1)
       faraday-net_http (>= 2.0, < 3.2)
       logger
-    faraday-net_http (3.1.0)
+    faraday-net_http (3.1.1)
       net-http
     ffi (1.17.0)
     ffi-compiler (1.3.2)
@@ -253,8 +253,8 @@ GEM
       ffi (>= 1.0.0)
     globalid (1.2.1)
       activesupport (>= 6.1)
-    google-protobuf (3.25.3)
-    hashdiff (1.1.0)
+    google-protobuf (3.25.4)
+    hashdiff (1.1.1)
     hashie (5.0.0)
     highline (3.1.0)
       reline
@@ -284,7 +284,7 @@ GEM
       image_optim (~> 0.24)
       railties
       sprockets
-    image_processing (1.12.2)
+    image_processing (1.13.0)
       mini_magick (>= 4.9.5, < 5)
       ruby-vips (>= 2.0.17, < 3)
     image_size (3.4.0)
@@ -352,7 +352,7 @@ GEM
     net-smtp (0.5.0)
       net-protocol
     nio4r (2.7.3)
-    nokogiri (1.16.6)
+    nokogiri (1.16.7)
       mini_portile2 (~> 2.8.2)
       racc (~> 1.4)
     oauth (0.4.7)
@@ -407,7 +407,7 @@ GEM
     parser (3.3.4.0)
       ast (~> 2.4.1)
       racc
-    pg (1.5.6)
+    pg (1.5.7)
     popper_js (2.11.8)
     progress (3.6.0)
     psych (5.1.2)
@@ -416,7 +416,7 @@ GEM
     puma (5.6.8)
       nio4r (~> 2.0)
     quad_tile (1.0.1)
-    racc (1.8.0)
+    racc (1.8.1)
     rack (2.2.9)
     rack-cors (2.0.2)
       rack (>= 2.0.0)
@@ -485,14 +485,14 @@ GEM
       io-console (~> 0.5)
     request_store (1.7.0)
       rack (>= 1.4)
-    rexml (3.3.2)
+    rexml (3.3.4)
       strscan
     rinku (2.0.6)
     rotp (6.3.0)
     rouge (4.3.0)
     rtlcss (0.2.1)
       mini_racer (>= 0.6.3)
-    rubocop (1.65.0)
+    rubocop (1.65.1)
       json (~> 2.3)
       language_server-protocol (>= 3.17.0)
       parallel (~> 1.10)
@@ -503,7 +503,7 @@ GEM
       rubocop-ast (>= 1.31.1, < 2.0)
       ruby-progressbar (~> 1.7)
       unicode-display_width (>= 2.4.0, < 3.0)
-    rubocop-ast (1.31.3)
+    rubocop-ast (1.32.0)
       parser (>= 3.3.1.0)
     rubocop-capybara (2.21.0)
       rubocop (~> 1.41)
@@ -528,7 +528,7 @@ GEM
       ffi (~> 1.12)
       logger
     rubyzip (2.3.2)
-    sanitize (6.1.1)
+    sanitize (6.1.2)
       crass (~> 1.0.2)
       nokogiri (>= 1.12.0)
     sass-embedded (1.64.2)
@@ -558,7 +558,7 @@ GEM
     sprockets-exporters_pack (0.1.2)
       brotli (>= 0.2.0)
       sprockets (>= 4.0.0.beta3)
-    sprockets-rails (3.5.1)
+    sprockets-rails (3.5.2)
       actionpack (>= 6.1)
       activesupport (>= 6.1)
       sprockets (>= 3.0.0)
@@ -597,7 +597,7 @@ GEM
     websocket-extensions (0.1.5)
     xpath (3.2.0)
       nokogiri (~> 1.8)
-    zeitwerk (2.6.16)
+    zeitwerk (2.6.17)
 
 PLATFORMS
   ruby
index f27dd2e63a515d0a0bf51571b6a49d6a5032c954..44e67634552599c861f9320209e8a7810a155edd 100644 (file)
@@ -19,6 +19,8 @@ class ApiCapability
         can [:gpx_files], User if scope?(token, :read_gpx)
         can [:index, :show], UserPreference if scope?(token, :read_prefs)
         can [:update, :update_all, :destroy], UserPreference if scope?(token, :write_prefs)
+        can [:inbox, :outbox, :show, :update, :destroy], Message if scope?(token, :consume_messages)
+        can [:create], Message if scope?(token, :send_messages)
 
         if user.terms_agreed?
           can [:create, :update, :upload, :close, :subscribe, :unsubscribe], Changeset if scope?(token, :write_api)
index 3036f169b07ed34c6ec3d45b9176c21e01dcc23a..259b914de614f6d2762cbd4beb3e07ca7adc0843 100644 (file)
@@ -1,7 +1,4 @@
 $(document).ready(function () {
-  /* Hide the preview panes */
-  $(".richtext_preview").hide();
-
   /*
    * When the text in an edit pane is changed, clear the contents of
    * the associated preview pne so that it will be regenerated when
@@ -11,34 +8,10 @@ $(document).ready(function () {
     $(this).parents(".richtext_container").find(".richtext_preview").empty();
   });
 
-  /* Disable all the edit buttons */
-  $(".richtext_doedit").prop("disabled", true);
-
-  /* Enable the preview buttons */
-  $(".richtext_dopreview").prop("disabled", false);
-
-  /*
-   * Install a click handler to switch to edit mode when the
-   * edit button is pressed.
-   */
-  $(".richtext_doedit").click(function (event) {
-    var editor = $(this).parents(".richtext_container").find("textarea");
-    var preview = $(this).parents(".richtext_container").find(".richtext_preview");
-
-    preview.hide();
-    editor.show();
-
-    $(this).siblings(".richtext_dopreview").prop("disabled", false);
-    $(this).prop("disabled", true);
-
-    event.preventDefault();
-  });
-
   /*
-   * Install a click handler to switch to preview mode when the
-   * preview button is pressed.
+   * Install a handler to switch to preview mode
    */
-  $(".richtext_dopreview").click(function (event) {
+  $(".richtext_dopreview").on("show.bs.tab", function () {
     var editor = $(this).parents(".richtext_container").find("textarea");
     var preview = $(this).parents(".richtext_container").find(".richtext_preview");
     var minHeight = editor.outerHeight() - preview.outerHeight() + preview.height();
@@ -54,13 +27,6 @@ $(document).ready(function () {
       });
     }
 
-    editor.hide();
     preview.css("min-height", minHeight + "px");
-    preview.show();
-
-    $(this).siblings(".richtext_doedit").prop("disabled", false);
-    $(this).prop("disabled", true);
-
-    event.preventDefault();
   });
 });
diff --git a/app/controllers/api/messages_controller.rb b/app/controllers/api/messages_controller.rb
new file mode 100644 (file)
index 0000000..074f873
--- /dev/null
@@ -0,0 +1,149 @@
+# The MessagesController is the RESTful interface to Message objects
+
+module Api
+  class MessagesController < ApiController
+    before_action :authorize
+
+    before_action :check_api_writable, :only => [:create, :update, :destroy]
+    before_action :check_api_readable, :except => [:create, :update, :destroy]
+
+    authorize_resource
+
+    around_action :api_call_handle_error, :api_call_timeout
+
+    before_action :set_request_formats
+
+    def inbox
+      @skip_body = true
+      @messages = Message.includes(:sender, :recipient).where(:to_user_id => current_user.id)
+
+      show_messages
+    end
+
+    def outbox
+      @skip_body = true
+      @messages = Message.includes(:sender, :recipient).where(:from_user_id => current_user.id)
+
+      show_messages
+    end
+
+    # Dump the details on a message given in params[:id]
+    def show
+      @message = Message.includes(:sender, :recipient).find(params[:id])
+
+      raise OSM::APIAccessDenied if current_user.id != @message.from_user_id && current_user.id != @message.to_user_id
+
+      # Render the result
+      respond_to do |format|
+        format.xml
+        format.json
+      end
+    end
+
+    # Create a new message from current user
+    def create
+      # Check the arguments are sane
+      raise OSM::APIBadUserInput, "No title was given" if params[:title].blank?
+      raise OSM::APIBadUserInput, "No body was given" if params[:body].blank?
+
+      # Extract the arguments
+      if params[:recipient_id]
+        recipient_id = params[:recipient_id].to_i
+        recipient = User.find(recipient_id)
+      elsif params[:recipient]
+        recipient_display_name = params[:recipient]
+        recipient = User.find_by(:display_name => recipient_display_name)
+      else
+        raise OSM::APIBadUserInput, "No recipient was given"
+      end
+
+      raise OSM::APIRateLimitExceeded if current_user.sent_messages.where(:sent_on => Time.now.utc - 1.hour..).count >= current_user.max_messages_per_hour
+
+      @message = Message.new(:sender => current_user,
+                             :recipient => recipient,
+                             :sent_on => Time.now.utc,
+                             :title => params[:title],
+                             :body => params[:body],
+                             :body_format => "markdown")
+      @message.save!
+
+      UserMailer.message_notification(@message).deliver_later if @message.notify_recipient?
+
+      # Return a copy of the new message
+      respond_to do |format|
+        format.xml { render :action => :show }
+        format.json { render :action => :show }
+      end
+    end
+
+    # Update read status of a message
+    def update
+      @message = Message.find(params[:id])
+      read_status_idx = %w[true false].index params[:read_status]
+
+      raise OSM::APIBadUserInput, "Invalid value of `read_status` was given" if read_status_idx.nil?
+      raise OSM::APIAccessDenied unless current_user.id == @message.to_user_id
+
+      @message.message_read = read_status_idx.zero?
+      @message.save!
+
+      # Return a copy of the message
+      respond_to do |format|
+        format.xml { render :action => :show }
+        format.json { render :action => :show }
+      end
+    end
+
+    # Delete message by marking it as not visible for the current user
+    def destroy
+      @message = Message.find(params[:id])
+      if current_user.id == @message.from_user_id
+        @message.from_user_visible = false
+      elsif current_user.id == @message.to_user_id
+        @message.to_user_visible = false
+      else
+        raise OSM::APIAccessDenied
+      end
+
+      @message.save!
+
+      # Return a copy of the message
+      respond_to do |format|
+        format.xml { render :action => :show }
+        format.json { render :action => :show }
+      end
+    end
+
+    private
+
+    def show_messages
+      @messages = @messages.where(:muted => false)
+      if params[:order].nil? || params[:order] == "newest"
+        @messages = @messages.where(:id => ..params[:from_id]) unless params[:from_id].nil?
+        @messages = @messages.order(:id => :desc)
+      elsif params[:order] == "oldest"
+        @messages = @messages.where(:id => params[:from_id]..) unless params[:from_id].nil?
+        @messages = @messages.order(:id => :asc)
+      else
+        raise OSM::APIBadUserInput, "Invalid order specified"
+      end
+
+      limit = params[:limit]
+      if !limit
+        limit = Settings.default_message_query_limit
+      elsif !limit.to_i.positive? || limit.to_i > Settings.max_message_query_limit
+        raise OSM::APIBadUserInput, "Messages limit must be between 1 and #{Settings.max_message_query_limit}"
+      else
+        limit = limit.to_i
+      end
+
+      @messages = @messages.limit(limit)
+
+      # Render the result
+      respond_to do |format|
+        format.xml
+        format.json
+      end
+    end
+  end
+end
index eaf6ddf9c519021e5d9a0809585fb94edf0f85ce..9962c7efd5f019f0f333bc6174931a7f8791276e 100644 (file)
@@ -69,6 +69,7 @@ class DiaryEntriesController < ApplicationController
     if @entry
       @title = t ".title", :user => params[:display_name], :title => @entry.title
       @og_image = @entry.body.image
+      @og_image_alt = @entry.body.image_alt
       @comments = can?(:unhide, DiaryComment) ? @entry.comments : @entry.visible_comments
     else
       @title = t "diary_entries.no_such_entry.title", :id => params[:id]
index 5d63e79fd3937fc178791920477b3668129e92ce..58f0a11c9340bbd796082622f3d6dcdbe852d13d 100644 (file)
@@ -138,7 +138,12 @@ class SiteController < ApplicationController
   end
 
   def preview
-    render :html => RichText.new(params[:type], params[:text]).to_html
+    if params[:text].blank?
+      flash.now[:warning] = t("layouts.nothing_to_preview")
+      render :partial => "layouts/flash"
+    else
+      render :html => RichText.new(params[:type], params[:text]).to_html
+    end
   end
 
   def id
index 3ab217a601fc5bfe1319aefffb5bb2ce8510314b..664ac56815d6e541de2de2e839b04aa188867f38 100644 (file)
@@ -63,8 +63,9 @@ class UserBlocksController < ApplicationController
 
   def update
     if @valid_params
-      if @user_block.creator != current_user
-        flash[:error] = t(".only_creator_can_edit")
+      if current_user != @user_block.creator &&
+         current_user != @user_block.revoker
+        flash[:error] = t(@user_block.revoker ? ".only_creator_or_revoker_can_edit" : ".only_creator_can_edit")
         redirect_to :action => "edit"
       elsif @user_block.update(
         :ends_at => Time.now.utc + @block_period.hours,
index a41831ca69d98bc6e287c495ec94653817245b2b..ad24c73b2fb3c2115d3b0a19b4c3809f18cd0638 100644 (file)
@@ -1,15 +1,16 @@
 module OpenGraphHelper
   require "addressable/uri"
 
-  def opengraph_tags(title = nil, og_image = nil)
+  def opengraph_tags(title = nil, og_image = nil, og_image_alt = nil)
     tags = {
       "og:site_name" => t("layouts.project_name.title"),
       "og:title" => title || t("layouts.project_name.title"),
       "og:type" => "website",
-      "og:image" => og_image_url(og_image),
       "og:url" => url_for(:only_path => false),
       "og:description" => t("layouts.intro_text")
-    }
+    }.merge(
+      opengraph_image_properties(og_image, og_image_alt)
+    )
 
     safe_join(tags.map do |property, content|
       tag.meta(:property => property, :content => content)
@@ -18,12 +19,20 @@ module OpenGraphHelper
 
   private
 
-  def og_image_url(og_image)
+  def opengraph_image_properties(og_image, og_image_alt)
     begin
-      return Addressable::URI.join(root_url, og_image).normalize if og_image
+      if og_image
+        properties = {}
+        properties["og:image"] = Addressable::URI.join(root_url, og_image).normalize
+        properties["og:image:alt"] = og_image_alt if og_image_alt
+        return properties
+      end
     rescue Addressable::URI::InvalidURIError
       # return default image
     end
-    image_url("osm_logo_256.png")
+    {
+      "og:image" => image_url("osm_logo_256.png"),
+      "og:image:alt" => t("layouts.logo.alt_text")
+    }
   end
 end
index aec1146cb8da9c68fd100364be0b7a626a98ecd5..fbbeb3dffb48e376c1aeef5053ef39c166b2950b 100644 (file)
@@ -2,4 +2,20 @@ module TraceHelper
   def link_to_tag(tag)
     link_to(tag, :tag => tag, :page => nil)
   end
+
+  def trace_icon(trace, options = {})
+    options[:class] ||= "trace_image"
+    options[:alt] ||= ""
+
+    image_tag trace_icon_path(trace.user, trace),
+              options.merge(:size => 50)
+  end
+
+  def trace_picture(trace, options = {})
+    options[:class] ||= "trace_image"
+    options[:alt] ||= ""
+
+    image_tag trace_picture_path(trace.user, trace),
+              options.merge(:size => 250)
+  end
 end
index f52d69865d9d2f63f3205641f9d5c028e52b1e5c..ce094fa3457ef5fb21093f6eba365c4fda5fb5cb 100644 (file)
@@ -1,5 +1,5 @@
 json.partial! "api/root_attributes"
 
-json.changesets(@changesets) do |changeset|
-  json.partial! changeset
+json.changesets do
+  json.array! @changesets, :partial => "changeset", :as => :changeset
 end
index 5ff7e262044032609666cd2deeada933bb917fb6..286f50c357cd8e1af8678dd5a0544014cb1f0c50 100644 (file)
@@ -1,7 +1,4 @@
 xml.instruct! :xml, :version => "1.0"
-
 xml.osm(OSM::API.new.xml_root_attributes) do |osm|
-  @changesets.each do |changeset|
-    osm << render(changeset)
-  end
+  osm << (render(@changesets) || "")
 end
diff --git a/app/views/api/messages/_message.json.jbuilder b/app/views/api/messages/_message.json.jbuilder
new file mode 100644 (file)
index 0000000..a04295d
--- /dev/null
@@ -0,0 +1,17 @@
+json.id message.id
+json.from_user_id message.from_user_id
+json.from_display_name message.sender.display_name
+json.to_user_id message.to_user_id
+json.to_display_name message.recipient.display_name
+json.title message.title
+json.sent_on message.sent_on.xmlschema
+
+if current_user.id == message.from_user_id
+  json.deleted !message.from_user_visible
+elsif current_user.id == message.to_user_id
+  json.message_read message.message_read
+  json.deleted !message.to_user_visible
+end
+
+json.body_format message.body_format
+json.body message.body unless @skip_body
diff --git a/app/views/api/messages/_message.xml.builder b/app/views/api/messages/_message.xml.builder
new file mode 100644 (file)
index 0000000..64ac9e3
--- /dev/null
@@ -0,0 +1,21 @@
+attrs = {
+  "id" => message.id,
+  "from_user_id" => message.from_user_id,
+  "from_display_name" => message.sender.display_name,
+  "to_user_id" => message.to_user_id,
+  "to_display_name" => message.recipient.display_name,
+  "sent_on" => message.sent_on.xmlschema,
+  "body_format" => message.body_format
+}
+
+if current_user.id == message.from_user_id
+  attrs["deleted"] = !message.from_user_visible
+elsif current_user.id == message.to_user_id
+  attrs["message_read"] = message.message_read
+  attrs["deleted"] = !message.to_user_visible
+end
+
+xml.message(attrs) do |nd|
+  nd.title(message.title)
+  nd.body(message.body) unless @skip_body
+end
diff --git a/app/views/api/messages/inbox.json.jbuilder b/app/views/api/messages/inbox.json.jbuilder
new file mode 100644 (file)
index 0000000..122a824
--- /dev/null
@@ -0,0 +1,5 @@
+json.partial! "api/root_attributes"
+
+json.messages do
+  json.array! @messages, :partial => "message", :as => :message
+end
diff --git a/app/views/api/messages/inbox.xml.builder b/app/views/api/messages/inbox.xml.builder
new file mode 100644 (file)
index 0000000..0ef9003
--- /dev/null
@@ -0,0 +1,7 @@
+xml.instruct!
+
+xml.osm(OSM::API.new.xml_root_attributes) do |osm|
+  xml.tag! "messages" do
+    osm << (render(@messages) || "")
+  end
+end
diff --git a/app/views/api/messages/outbox.json.jbuilder b/app/views/api/messages/outbox.json.jbuilder
new file mode 100644 (file)
index 0000000..122a824
--- /dev/null
@@ -0,0 +1,5 @@
+json.partial! "api/root_attributes"
+
+json.messages do
+  json.array! @messages, :partial => "message", :as => :message
+end
diff --git a/app/views/api/messages/outbox.xml.builder b/app/views/api/messages/outbox.xml.builder
new file mode 100644 (file)
index 0000000..440e342
--- /dev/null
@@ -0,0 +1,5 @@
+xml.instruct!
+
+xml.osm(OSM::API.new.xml_root_attributes) do |osm|
+  osm << (render(@messages) || "")
+end
diff --git a/app/views/api/messages/show.json.jbuilder b/app/views/api/messages/show.json.jbuilder
new file mode 100644 (file)
index 0000000..d8f24e9
--- /dev/null
@@ -0,0 +1,5 @@
+json.partial! "api/root_attributes"
+
+json.message do
+  json.partial! @message
+end
diff --git a/app/views/api/messages/show.xml.builder b/app/views/api/messages/show.xml.builder
new file mode 100644 (file)
index 0000000..008d592
--- /dev/null
@@ -0,0 +1,5 @@
+xml.instruct! :xml, :version => "1.0"
+
+xml.osm(OSM::API.new.xml_root_attributes) do |osm|
+  osm << render(@message)
+end
index 7909391f5ae939f231121b01c958134ad0afce72..5660a8ad5038b0006b0b0f2fd6abd7709d06cbfc 100644 (file)
@@ -1,5 +1,5 @@
 json.type "FeatureCollection"
 
-json.features(@notes) do |note|
-  json.partial! note
+json.features do
+  json.array! @notes, :partial => "note", :as => :note
 end
index 1ad07d47cd2639cc63d49ae093b9785478a5868b..d2dbd4d4f5c6113fd03a381e779215dabe3e58c4 100644 (file)
@@ -1,5 +1,5 @@
 json.partial! "api/root_attributes"
 
-json.users(@users) do |user|
-  json.partial! user
+json.users do
+  json.array! @users, :partial => "user", :as => :user
 end
index cb48d834e378798fa747cda8c0dc8e849449aad5..e96564b82b84839d0ab4d15bbfe998b9d80b1d58 100644 (file)
@@ -82,7 +82,7 @@
     <% if current_user && current_user.id %>
       <div class='d-inline-flex dropdown user-menu logged-in'>
         <button class='d-flex gap-1 align-items-center justify-content-center dropdown-toggle btn btn-outline-secondary border-secondary-subtle bg-body text-secondary px-2 py-1 flex-grow-1' type='button' data-bs-toggle='dropdown'>
-          <%= user_thumbnail_tiny(current_user, :width => 25, :height => 25, :class => "user_thumbnail_tiny rounded-1 bg-body") %>
+          <%= user_thumbnail_tiny(current_user, :class => "user_thumbnail_tiny rounded-1 bg-body") %>
           <% if current_user.new_messages.size > 0 %>
             <span class="badge count-number position-static m-1"><%= current_user.new_messages.size %></span>
           <% end %>
index 37afbb89498e5cc67a2e101a17c4e83d312bc62f..f09449761a4990c9226fb17c4b9cf64e4fc0d533 100644 (file)
@@ -21,7 +21,7 @@
 <% end -%>
 <%= tag.link :rel => "search", :type => "application/opensearchdescription+xml", :title => "OpenStreetMap Search", :href => asset_path("osm.xml") %>
 <%= tag.meta :name => "description", :content => "OpenStreetMap is the free wiki world map." %>
-<%= opengraph_tags(@title, @og_image) %>
+<%= opengraph_tags(@title, @og_image, @og_image_alt) %>
 <% if flash[:matomo_goal] -%>
 <%= tag.meta :name => "matomo-goal", :content => flash[:matomo_goal] %>
 <% end -%>
index f471cbbbf93bf89457e081abaa67ec5a91c67aa3..23817576276da21b53d39c9ad8c3b3b819092adb 100644 (file)
@@ -1,14 +1,24 @@
 <div id="<%= id %>_container" class="row richtext_container">
   <div id="<%= id %>_content" class="col-sm-8 mb-3 mb-sm-0 richtext_content">
-    <%= builder.text_area(attribute, options.merge(:wrapper => false, "data-preview-url" => preview_url(:type => type))) %>
-    <div id="<%= id %>_preview" class="richtext_preview richtext text-break"></div>
+    <ul class="nav nav-tabs mb-3" role="tablist">
+      <li class="nav-item">
+        <button type="button" class="nav-link active" data-bs-toggle="tab" data-bs-target="#<%= id %>_edit"><%= t(".edit") %></button>
+      </li>
+      <li class="nav-item">
+        <button type="button" class="nav-link richtext_dopreview" data-bs-toggle="tab" data-bs-target="#<%= id %>_preview"><%= t(".preview") %></button>
+      </li>
+    </ul>
+    <div class="tab-content">
+      <div id="<%= id %>_edit" class="tab-pane show active">
+        <%= builder.text_area(attribute, options.merge(:wrapper => false, "data-preview-url" => preview_url(:type => type))) %>
+      </div>
+      <div id="<%= id %>_preview" class="tab-pane richtext_preview richtext text-break"></div>
+    </div>
   </div>
   <div id="<%= id %>_help" class="col-sm-4 richtext_help">
     <div class="card bg-body-tertiary h-100">
       <div class="card-body">
         <%= render :partial => "shared/#{type}_help" %>
-        <%= submit_tag t(".edit"), :id => "#{id}_doedit", :class => "richtext_doedit btn btn-primary", :disabled => true %>
-        <%= submit_tag t(".preview"), :id => "#{id}_dopreview", :class => "richtext_dopreview btn btn-primary" %>
       </div>
     </div>
   </div>
index ba503f7306d335b8eb43d580bd4c33488710d864..f60eea7f1cbe22834e631359484b592f6cddb0a7 100644 (file)
@@ -2,7 +2,7 @@
   <td>
     <% if Settings.status != "gpx_offline" %>
       <% if trace.inserted %>
-        <%= link_to image_tag(trace_icon_path(trace.user, trace), :alt => "", :class => "trace_image"),
+        <%= link_to trace_icon(trace),
                     show_trace_path(trace.user, trace),
                     :class => "d-inline-block" %>
       <% else %>
index 2059178cfa91303ca496f68839d590f6db097141..1c440adf25432440ac04b2f1dc330f137df66617 100644 (file)
@@ -2,7 +2,7 @@
   <h1><%= t ".heading", :name => @trace.name %></h1>
 <% end %>
 
-<%= image_tag trace_picture_path(@trace.user, @trace), :class => "trace_image" %>
+<%= trace_picture(@trace) %>
 
 <%= bootstrap_form_for @trace do |f| %>
   <%= f.text_field :name, :disabled => true %>
index 51b21f9828e0f72cfdd56488f0e6657e9098a442..63adf15729c5aaa662d2f4f3d111b6d4d00de5c7 100644 (file)
@@ -4,7 +4,7 @@
 
 <% if Settings.status != "gpx_offline" %>
   <% if @trace.inserted %>
-    <%= image_tag trace_picture_path(@trace.user, @trace), :class => "trace_image" %>
+    <%= trace_picture(@trace) %>
   <% else %>
     <span class="text-danger"><%= t ".pending" %></span>
   <% end %>
index 461dc7a8d9e8ef6c19b34a80ce1a05900c17455f..a18d1dbdbabe51a753515e138fad795483d2b422 100644 (file)
@@ -15,7 +15,8 @@
     <% end %>
   </td>
   <td><%= link_to t(".show"), block %></td>
-  <td><% if current_user and current_user.id == block.creator_id %><%= link_to t(".edit"), edit_user_block_path(block) %><% end %></td>
+  <td><% if current_user && (current_user.id == block.creator_id ||
+                             current_user.id == block.revoker_id) %><%= link_to t(".edit"), edit_user_block_path(block) %><% end %></td>
   <% if show_revoke_link %>
   <td><% if block.active? %><%= link_to t(".revoke"), revoke_user_block_path(block) %><% end %></td>
   <% end %>
index 619cd6c3f0c58d3fdee045698ca72b59882fd0b2..c36c043cf80434d2f3120bf767154c69fb33323a 100644 (file)
   <dd class="col-sm-9"><div class="richtext text-break"><%= @user_block.reason.to_html %></div></dd>
 </dl>
 
-<% if current_user&.id == @user_block.creator_id || can?(:revoke, UserBlock) && @user_block.active? %>
+<% if current_user && (current_user.id == @user_block.creator_id ||
+                       current_user.id == @user_block.revoker_id) ||
+      can?(:revoke, UserBlock) && @user_block.active? %>
   <div>
-    <% if current_user&.id == @user_block.creator_id %>
+    <% if current_user && (current_user.id == @user_block.creator_id ||
+                           current_user.id == @user_block.revoker_id) %>
       <%= link_to t(".edit"), edit_user_block_path(@user_block), :class => "btn btn-outline-primary" %>
     <% end %>
     <% if can?(:revoke, UserBlock) && @user_block.active? %>
diff --git a/app/views/user_mailer/_gpx_description.text.erb b/app/views/user_mailer/_gpx_description.text.erb
new file mode 100644 (file)
index 0000000..6f7a978
--- /dev/null
@@ -0,0 +1,8 @@
+<% trace_name = @trace_name %>
+<% trace_description = @trace_description %>
+<% if @trace_tags.length > 0 %>
+  <% tags = @trace_tags.map { |trace_tag| trace_tag.tag }.join(", ") %>
+  <%= t ".description_with_tags", :trace_name => trace_name, :trace_description => trace_description, :tags => tags %>
+<% else %>
+  <%= t ".description_with_no_tags", :trace_name => trace_name, :trace_description => trace_description %>
+<% end %>
diff --git a/app/views/user_mailer/gpx_failure.text.erb b/app/views/user_mailer/gpx_failure.text.erb
new file mode 100644 (file)
index 0000000..9544c74
--- /dev/null
@@ -0,0 +1,10 @@
+<%= t ".hi", :to_user => @to_user %>
+
+<%= render :partial => "gpx_description" %>
+<%= t ".failed_to_import" %>
+
+==
+<%= @error %>
+==
+
+<%= t ".more_info", :url => t(".import_failures_url") %>
diff --git a/app/views/user_mailer/gpx_success.text.erb b/app/views/user_mailer/gpx_success.text.erb
new file mode 100644 (file)
index 0000000..aee3a0f
--- /dev/null
@@ -0,0 +1,8 @@
+<%= t ".hi", :to_user => @to_user %>
+
+<%= render :partial => "gpx_description" %>
+<%= t(".loaded", :trace_points => @trace_points, :count => @possible_points) %>
+
+<%= t ".trace_location", :trace_url => @trace_url %>
+
+<%= t ".all_your_traces", :url => @my_traces_url %>
index a924af237af9dcf333557c83e03a9cb4142c6a02..d92818493a6aef6a5899fcf53d616b4da694a341 100644 (file)
@@ -1173,7 +1173,6 @@ aln:
       show: Shiko këtë bllok
       back: Shiko të gjitha blloqet e
     filter:
-      block_expired: Blloku ka skaduar dhe nuk mund të redaktohen.
       block_period: Periudha e bllokuar duhet të jetë një nga vlerat selectable në
         drop-down list.
     create:
index d8cc0a6f558e20f48a8dc669da6dba7c488ffc85..3fc7c8e6b54e011af11103825a24fdf3905ed48e 100644 (file)
@@ -44,6 +44,7 @@
 # Author: Zpizza
 # Author: أَحمد
 # Author: بدارين
+# Author: بهتين شوكت
 # Author: ترجمان05
 # Author: حبيشان
 # Author: ديفيد
@@ -1663,18 +1664,28 @@ ar:
       befriend_them: "\uFEFFيمكنك أيضًا إضافتهم كصديق على %{befriendurl}."
       befriend_them_html: يمكنك أيضًا إضافتهم كصديق على %{befriendurl}.
     gpx_description:
+      description_with_tags: 'ويبدو ذالك ملف GPX الخاص بك هو %{trace_name} مع الوصف
+        %{trace_description} والعلامات التالية: %{tags}'
       description_with_tags_html: 'يبدو أن ملف GPX الخاص بك %{trace_name} مع الوصف
         %{trace_description} والعلامات التالية: %{tags}'
+      description_with_no_tags: يبدو أن ملف GPX الخاص بك %{trace_name} ومع ذالك الوصف
+        %{trace_description} وبدون وسوم
       description_with_no_tags_html: يبدو أن ملف GPX الخاص بك %{trace_name} مع الوصف
         %{trace_description} وبدون وسوم
     gpx_failure:
       hi: مرحبًا %{to_user}،
       failed_to_import: 'فشل الاستيراد، الخطأ هو:'
+      more_info: أكثر معلومة عن جي بي اكس يستورد الفشل و كيف ل يتجنب هم يستطيع يكون
+        وجد في%{url}.
       more_info_html: يمكن العثور على مزيد من المعلومات حول إخفاقات استيراد GPX وكيفية
         تجنبها على %{url}.
       subject: '[خريطة الشارع المفتوحة] فشل استيراد جي بي إكس'
     gpx_success:
       hi: مرحبًا %{to_user}،
+      trace_location: لك يتعقب يكون ذالك متاح في %{trace_url}
+      all_your_traces: |-
+        ان الجميع لك بنجاح اترفع جي بي اكس آثار وهو موجود في
+        %{url}
       subject: '[خريطة الشارع المفتوحة] نجاح استيراد جي بي إكس'
     signup_confirm:
       subject: '[خريطة الشارع المفتوحة] مرحبا بك في خريطة الشارع المفتوحة'
@@ -2618,13 +2629,14 @@ ar:
       show: اعرض هذه العرقلة
       back: اعرض كل العرقلات
     filter:
-      block_expired: العرقلة قد انتهت ولا يمكن تعديلها.
       block_period: فترة العرقلة يجب أن تكون واحدة من القيم الاختيارية في القائمة
         المنسدلة.
     create:
       flash: أُنشىء عرقلة على المستخدم %{name}.
     update:
       only_creator_can_edit: فقط الوسيط الذي قام بإنشاء هذه العرقلة يمكنه تعديلها.
+      only_creator_or_revoker_can_edit: لاينفع تعديل هذا الحظر إلا من المشرفين الذين
+        العملوا هذا الحظر أو إلغائه.
       success: تم تحديث العرقلة.
     index:
       title: عرقلات المستخدم
index 762f819c5d388e2c9f04053ba124164c268f7772..30cd031181e2743f5801dee2b9d0aad57cec025e 100644 (file)
@@ -989,7 +989,6 @@ arz:
       show: اعرض هذه العرقلة
       back: اعرض كل العرقلات
     filter:
-      block_expired: العرقله قد انتهت ولا يمكن تعديلها.
       block_period: فتره العرقله يجب أن تكون واحده من القيم الاختياريه فى القائمه
         المنسدله.
     create:
index 1a8715510564b1e74b75b0e5d11fd2e6d8c4d640..b5b930b7d3a9449c47b0817dcae47783baa2d55a 100644 (file)
@@ -2070,7 +2070,6 @@ ast:
       show: Ver esti bloquéu
       back: Ver tolos bloqueos
     filter:
-      block_expired: El bloquéu yá caducó y nun puede editase.
       block_period: El periodu de bloquéu tien de ser un de los valores presentes
         na llista estenderexable.
     create:
index 87af26366df5f60471a04c2771a26646e1def3fd..d2b1c812c79540c5e624db1dd6055ff861ae663b 100644 (file)
@@ -1458,7 +1458,6 @@ be-Tarask:
       show: Паказаць гэтае блякаваньне
       back: Паказаць усе блякаваньні
     filter:
-      block_expired: Блякаваньне ўжо скончылася і ня можа рэдагавацца.
       block_period: Час блякаваньня павінен быць выбраны са значэньняў з разгортваемага
         сьпісу.
     create:
index 5bf21b9c7958179aa6c249b940e21bc6ac11886f..8ed552833e24e7fe449543b6a8b7b17fc74f2407 100644 (file)
@@ -699,6 +699,8 @@ be:
       comment: Каментар
       newer_comments: Навейшыя каментары
       older_comments: Старэйшыя каментары
+    new:
+      heading: Дадаць каментар да абмеркавання наступнага запісу ў дзённіку?
   doorkeeper:
     errors:
       messages:
@@ -940,6 +942,7 @@ be:
           college: Будынак каледжа
           commercial: Камерцыйны будынак
           construction: Будынак будуецца
+          cowshed: Кароўнік
           detached: Хата
           dormitory: Інтэрнат
           duplex: Падзеленая хата
@@ -969,6 +972,7 @@ be:
           shed: Адрына
           stable: Стайня
           static_caravan: Мабільны дом
+          sty: Свінарнік
           temple: Храм
           terrace: Тэраса
           train_station: Чыгуначны вакзал
@@ -2027,7 +2031,7 @@ be:
       lost password link: Згубілі пароль?
       login_button: Увайсці
       register now: Зарэгістравацца зараз
-      with external: або ўвайдзіце ў сістэму з дапамогай трэцяй асобы
+      with external: або ўвайдзіце ў сістэму з дапамогай пабочнага сэрвісу
       or: або
       auth failure: Прабачце, немагчыма увайсці з такім адрасам і паролем.
     destroy:
@@ -2089,6 +2093,15 @@ be:
       open_data_open_data: адкрытыя даныя
       open_data_copyright_license: Аўтарскія правы і ліцэнзія
       legal_title: Прававыя пытанні
+      legal_1_1_openstreetmap_foundation: Фонд OpenStreetMap
+      legal_1_1_terms_of_use: Умовы карыстання
+      legal_1_1_privacy_policy: Палітыка прыватнасці
+      legal_2_1_html: Калі ласка, %{contact_the_osmf_link}, калі ў вас ёсць пытанні
+        адносна ліцэнзавання, аўтарскіх правоў або іншых юрыдычных пытаннях.
+      legal_2_1_contact_the_osmf: звяжыцеся з Фондам OSM
+      legal_2_2_html: OpenStreetMap, лагатып у відзе павелічальнага шкла і State of
+        the Map з'яўляюцца %{registered_trademarks_link}.
+      legal_2_2_registered_trademarks: зарэгістраванымі таварнымі знакамі Фонду OSM
       partners_title: Партнёры
     copyright:
       title: Аўтарскія правы і ліцэнзія
@@ -2105,6 +2118,16 @@ be:
         native_link: беларуская версія
         mapping_link: пачаць маляваць карту
       legal_babble:
+        introduction_1_osm_foundation: Фонд OpenStreetMap
+        introduction_2_html: Вы можаце капіраваць, распаўсюджваць, перадаваць і змяняць
+          нашыя даныя да той пары пакуль вы спасылаецеся на OpenStreetMap і яе ўдзельнікаў.
+          Калі вы змяняеце ці выкарыстоўваеце нашыя даныя, то можаце распаўсюджваць
+          вынікі толькі на ўмовах такой жа ліцэнзіі. Поўны %{legal_code_link} растлумачыць
+          вашыя правы і абавязкі.
+        introduction_2_legal_code: тэкст ліцэнзіі
+        introduction_3_html: Наша дакументацыя прадастаўляецца на ўмовах ліцэнзіі
+          %{creative_commons_link} (CC BY-SA 2.0).
+        introduction_3_creative_commons: Creative Commons Attribution-ShareAlike 2.0
         credit_title_html: Як спасылацца на OpenStreetMap
         credit_1_html: 'Там, дзе вы выкарыстоўваеце даныя OpenStreetMap, вы павінны
           выканаць наступныя дзве рэчы:'
@@ -2116,6 +2139,25 @@ be:
         contributors_intro_html: 'Нашымі ўдзельнікамі з''яўляюцца тысячы людзей. Мы
           таксама ўключаем дадзеныя ад нацыянальных картаграфічных агенцтваў, якія
           распаўсюджваюцца на ўмовах адкрытых ліцэнзій, сярод іх:'
+        contributors_at_austria: |2-
+           Пераключыць змест
+
+          Аўстрыя
+        contributors_au_australia: |2-
+           Пераключыць змест
+
+          Аўстралія
+        contributors_ca_canada: Канада
+        contributors_cz_czechia: Чэхія
+        contributors_fi_finland: Фінляндыя
+        contributors_fr_france: Францыя
+        contributors_hr_croatia: Харватыя
+        contributors_nl_netherlands: Нідэрланды
+        contributors_nz_new_zealand: Новая Зеландыя
+        contributors_rs_serbia: Сербія
+        contributors_si_slovenia: Славенія
+        contributors_es_spain: Іспанія
+        contributors_za_south_africa: Паўднёвая Афрыка
         contributors_footer_2_html: |-
           Уключэнне дадзеных у OpenStreetMap не азначае, што пастаўшчыкі пачатковых дадзеных
           якім-небудзь чынам падтрымліваюць OpenStreetMap, прадстаўляюць гарантыі, ці
@@ -2243,6 +2285,8 @@ be:
           rail: Чыгунка
           train: Цягнік
           subway: Метро
+          ferry: Паром
+          tram: Трамвай
           trolleybus: Тралейбус
           bus: Аўтобус
           cable_car: Канатная дарога
@@ -2251,8 +2295,11 @@ be:
           taxiway: рулёжная дарожка
           apron: Перон аэрапорта
           admin: Адміністрацыйная мяжа
+          capital: Сталіца
+          city: Горад
           forest: Лес
           wood: пушча
+          sand: Пясок
           golf: Поле для гольфа
           park: Парк
           common: Агульныя
@@ -2274,15 +2321,17 @@ be:
           military: Ваенная зона
           school: Школа
           university: Універсітэт
+          hospital: Бальніца
           building: Значны будынак
           station: Чыгуначны вакзал
           summit: Вяршыня
-          peak: Ð¿ік
+          peak: Ð\9fік
           tunnel: Тунэль (пункцірам)
           bridge: Мост (суцэльная лінія)
           private: Прыватны доступ
           destination: Мэтавы доступ
           construction: Дарогі ў стадыі будаўніцтва
+          bus_stop: Аўтобусны прыпынак
           bicycle_shop: Крама ровараў
           bicycle_parking: Паркоўка для ровараў
           toilets: Прыбіральні
@@ -2524,18 +2573,49 @@ be:
       flash: Кліенцкая інфармацыя была абноўленая паспяхова
     destroy:
       flash: Знішчаная рэгістрацыя кліенцкага дастасавання
+  oauth2_applications:
+    index:
+      new: Зарэгістраваць новую праграму
+      name: Назва
+      permissions: Дазволы
+    application:
+      edit: Рэдагаваць
+      delete: Выдаліць
+    new:
+      title: Зарэгістраваць новую праграму
+    show:
+      edit: Правіць
+      delete: Выдаліць
   users:
     new:
       title: Зарэгістравацца
+      tab_title: Зарэгістравацца
       no_auto_account_create: На жаль, мы не можам стварыць для вас уліковы запіс
         аўтаматычна.
       about:
         header: Свабодная і даступная для рэдагавання
+        paragraph_1: У адрозненне ад іншых карт, OpenStreetMap цалкам створана такімі
+          ж людзьмі як вы і кожны можа яе свабодна рэдагаваць і выкарыстоўваць.
+        paragraph_2: Зарэгіструйцеся, каб зрабіць свой унёсак.
+        welcome: Вітаем у OpenStreetMap
       display name description: Ваша імя, якое будзе бачнае ўсім. Вы можаце змяніць
         яго потым ў вашых параметрах.
+      by_signing_up:
+        html: Рэгіструючыся, вы пагаджаецеся з нашымі %{tou_link}, %{privacy_policy_link}
+          і %{contributor_terms_link}.
+        privacy_policy: палітыкай прыватнасці
+        contributor_terms: умовамі ўдзелу
+      tou: умовамі карыстання
       external auth: 'Аўтэнтыфікацыя праз:'
       continue: Зарэгістравацца
       terms accepted: Дзякуй за прыняцце новых умоў ўдзелу!
+      email_help:
+        privacy_policy: палітыкі прыватнасці
+        html: Адрас вашай электроннай пошты не будзе паказвацца іншым карыстальнікам,
+          звярніцеся да %{privacy_policy_link} за больш дэтальнай інфармацыяй.
+      consider_pd_html: Я пагаджаюся з тым, што мой унёсак будзе часткай %{consider_pd_link}.
+      consider_pd: грамадскага набытку
+      or: або
       use external auth: У якасці альтэрнатывы выкарыстайце для ўваходу старонні сервіс
     terms:
       title: Умовы
@@ -2588,6 +2668,9 @@ be:
       remove as friend: Выдаліць з сяброў
       add as friend: Пасябраваць
       mapper since: 'Малюе карту з:'
+      last map edit: 'Апошняе рэдагаванне карты:'
+      no activity yet: Актыўнасці пакуль няма
+      uid: 'ID карыстальніка:'
       ct status: 'Умовы ўдзелу:'
       ct undecided: Нявырашана
       ct declined: Адхіленыя
@@ -2598,18 +2681,24 @@ be:
       role:
         administrator: Гэты карыстальнік з’яўляецца адміністратарам
         moderator: Гэты карыстальнік з’яўляецца мадэратарам
+        importer: Гэты карыстальнік займаецца імпартам даных
         grant:
           administrator: Надаць правы адміністратара
           moderator: Надаць правы мадэратара
+          importer: Дазволіць карыстальніку імпарт даных
         revoke:
           administrator: Адклікаць доступ з правамі адміністратара
           moderator: Скасаваць доступ мадэратара
+          importer: Забараніць карыстальніку імпарт даных
       block_history: Дзейныя блакіроўкі
       moderator_history: Створаныя блакіроўкі
+      revoke_all_blocks: Скасаваць усе блакіроўкі
       comments: Каментары
       create_block: Заблакаваць гэтага карыстальніка
       activate_user: Актываваць гэтага карыстальніка
       confirm_user: Пацвердзіць гэтага карыстальніка
+      unconfirm_user: Адмяніць пацвярджэнне гэтага карыстальніка
+      unsuspend_user: Адмяніць прыпыненне ўліковага запісу гэтага карыстальніка
       hide_user: Схаваць гэтага карыстальніка
       unhide_user: Паказаць гэтага карыстальніка
       delete_user: Выдаліць гэтага карыстальніка
@@ -2620,6 +2709,8 @@ be:
     index:
       title: Удзельнікі
       heading: Удзельнікі
+      older: Даўнейшыя карыстальнікі
+      newer: Навейшыя карыстальнікі
       summary_html: '%{name} створана з %{ip_address} %{date}'
       summary_no_ip_html: '%{name} створаны %{date}'
       confirm: Пацвердзіць выбраных карыстальнікаў
@@ -2628,6 +2719,11 @@ be:
     suspended:
       title: Уліковы запіс прыпынены
       heading: Уліковы запіс прыпынены
+      support: службы падтрымкі
+      automatically_suspended: На жаль, ваш уліковы запіс быў прыпынены з-за падазронай
+        актыўнасці.
+      contact_support_html: Гэтае рашэнне будзе разгледжана адміністратарам у хуткім
+        часе або вы можаце напісаць да %{support_link}, калі вы жадаеце яго абмеркаваць.
     auth_failure:
       connection_failed: Злучэнне з крыніцай аўтэнтыфікацыі не атрымалася
       invalid_credentials: Памылковыя ўліковыя даныя для праверкі сапраўднасці
@@ -2683,7 +2779,6 @@ be:
       show: Паказаць гэтую блакіроўку
       back: Паказаць усе блакіроўкі
     filter:
-      block_expired: Блакіроўка ўжо скончылася і не можа рэдагавацца.
       block_period: Час блакіроўкі павінен быць выбраны са значэнняў з разгортваемага
         спісу.
     create:
@@ -2740,7 +2835,8 @@ be:
     show:
       title: '%{block_on} заблакіраваны %{block_by}'
       heading_html: '%{block_on} заблакіраваны %{block_by}'
-      created: Створаны
+      created: 'Створана:'
+      duration: 'Працягласць:'
       status: 'Статус:'
       show: Паказаць
       edit: Рэдагаваць
@@ -2761,11 +2857,17 @@ be:
       reason: Прычына блакіроўкі
       status: Статус
       revoker_name: Адкліканы
+  user_mutes:
+    index:
+      table:
+        tbody:
+          send_message: Даслаць паведамленне
   notes:
     index:
       title: Заўвагі, створаныя ці пракаментаваныя %{user}
       heading: Заўвагі %{user}'а
       subheading_html: Заўвагі, створаныя ці пракаментаваныя %{user}
+      no_notes: Няма запісаў
       id: Id
       creator: Стваральнік
       description: Апісанне
@@ -2777,6 +2879,10 @@ be:
       open_title: 'Нявырашаная заўвага #%{note_name}'
       closed_title: 'Вырашаная заўвага #%{note_name}'
       hidden_title: 'Схаваная заўвага #%{note_name}'
+      event_opened_by_html: Створана карыстальнікам %{user} %{time_ago}
+      event_opened_by_anonymous_html: Створана ананімным карыстальнікам %{time_ago}
+      event_commented_by_html: Пракаментавана карыстальнікам %{user} %{time_ago} таму
+      event_commented_by_anonymous_html: Пракаментавана ананімным карыстальнікам %{time_ago}
       report: паскардзіцца на гэтую заўвагу
       anonymous_warning: Гэтая нататка змяшчае каментары ад ананімных карыстальнікаў,
         што павінны быць незалежна правераны.
@@ -2790,6 +2896,7 @@ be:
       intro: Заўважылі памылку або чагосьці не стае? Дайце іншым удзельнікам магчымасць
         даведацца пра памылку і такім чынам мы выправім яе. Перамясціце маркер у патрэбную
         пазіцыю і напішыце заўвагу з тлумачэннем праблемы.
+      anonymous_warning_sign_up: Зарэгістравацца
       advice: Ваша заўвага агульнадаступная і можа выкарыстоўвацца для абнаўлення
         карты, таму не ўводзьце асабістую інфармацыю або інфармацыю з абароненых аўтарскім
         правам карт або рэестраў.
@@ -2850,6 +2957,9 @@ be:
         gps: Агульныя GPS-сляды
         overlays: Уключыць накладкі для ліквідацыі памылак карты
         title: Слаі
+      make_a_donation: Зрабіць ахвяраванне
+      website_and_api_terms: Умовы вэб-сайта і API
+      osm_france: OpenStreetMap Францыя
     site:
       edit_tooltip: Рэдагаваць карту
       edit_disabled_tooltip: Наблізце, каб рэдагаваць карту
@@ -2873,6 +2983,8 @@ be:
       descend: Уніз
       directions: Маршрут
       distance: Адлегласць
+      distance_m: '%{distance}м'
+      distance_km: '%{distance}км'
       errors:
         no_route: Не атрымалася знайсці маршрут паміж двума гэтымі месцамі.
         no_place: 'Прабачце - не магу знайсці гэта месца: %{place}.'
index ba58716d938887751aff1c5049696d3aa0ca8d26..67ecb6745853489fcb1aeaee9e5c3e0dacf10ebd 100644 (file)
@@ -1134,10 +1134,10 @@ bg:
           "yes": Воден път
       admin_levels:
         level2: Държавна граница
-        level4: Ð\94Ñ\8aÑ\80жавна Ð³Ñ\80аниÑ\86а
-        level5: Граница на региона
-        level6: Ð\9eблаÑ\81Ñ\82на Ð³Ñ\80аниÑ\86а
-        level7: Ð\9eбÑ\89инÑ\81ка Ð³Ñ\80аниÑ\86а
+        level4: Ð\93Ñ\80аниÑ\86а Ð½Ð° Ð¾Ð±Ð»Ð°Ñ\81Ñ\82
+        level5: Граница на община
+        level6: Ð\93Ñ\80аниÑ\86а Ð½Ð° Ñ\80айон
+        level7: Ð\93Ñ\80аниÑ\86а Ð½Ð° ÐºÐ¼ÐµÑ\82Ñ\81Ñ\82во
         level8: Граница на землище
         level9: Граница на селото
         level10: Граница на предградията
@@ -1495,7 +1495,9 @@ bg:
   shared:
     markdown_help:
       headings: Заглавия
+      heading: Заглавие
       subheading: Подзаглавие
+      unordered: Неподреден списък
       ordered: Подреден списък
       first: Първи елемент
       second: Втори елемент
@@ -1566,8 +1568,23 @@ bg:
         mapping_link: картографирате
       legal_babble:
         credit_title_html: Как да кредитирате OpenStreetMap
+        credit_1_html: 'Когато използвате данни от OpenStreetMap, от вас се изисква
+          да направите следните две неща:'
+        credit_2_1: Предоставете кредит към OpenStreetMap, като покажете нашето уведомление
+          за авторски права.
+        credit_2_2: Ясно да посочите, че данните са достъпни съгласно Лиценза за отворени
+          бази данни (Open Database License).
+        credit_3_html: По отношение на известието за авторските права имаме различни
+          изисквания за начина, по който то трябва да се показва, в зависимост от
+          това как използвате нашите данни. В зависимост от това дали сте създали
+          карта с възможност за преглед, печатна карта или статично изображение, се
+          прилагат различни правила за начина на показване на съобщението за авторски
+          права. Пълна информация за изискванията може да бъде намерена в %{attribution_guidelines_link}.
         more_title_html: Открийте повече
         contributors_title_html: Нашите сътрудници
+        contributors_intro_html: 'Нашите сътрудници са хиляди хора. Ние включваме
+          и данни, които са отворено лицензирани от национални картографски агенции
+          и други източници, сред които:'
         infringement_title_html: Нарушаване на авторските права
         infringement_1_html: Напомняме на сътрудниците на OSM никога да не добавят
           данни от източници, защитени с авторски права (например Google Maps или
@@ -1788,6 +1805,7 @@ bg:
           степен като местните клонове. Всъщност много групи съществуват много успешно
           като неформално събиране на хора или като общностна група. Всеки може да
           ги създаде или да се присъедини към тях. Прочетете повече на %{communities_wiki_link}.
+        communities_wiki: уики страница Общности
   traces:
     new:
       upload_trace: Качване на следи от GPS
@@ -1848,8 +1866,10 @@ bg:
     index:
       public_traces: Публични следи от GPS
       public_traces_from: Публични следи от GPS от потребител %{user}
+      description: Преглед на скорошни качвания на GPS следи
       tagged_with: с етикет %{tags}
       upload_trace: Качване на следи от GPS
+      all_traces: Всички следи
       my_traces: Моите следи
     georss:
       title: OpenStreetMap GPS трасета
@@ -2019,8 +2039,6 @@ bg:
     edit:
       title: Промяна на блокирането на %{name}
       heading_html: Промяна на блокирането на %{name}
-    filter:
-      block_expired: Блокирането вече е изтекло и не може да се редактира.
     revoke:
       revoke: Анулиране!
     helper:
index 96bf2e421a3f11091c58a91db1aa1266818dc7ec..548529766910c454459444c55d111036fc65e8bc 100644 (file)
@@ -2484,22 +2484,22 @@ br:
       openid_login_button: Kenderc'hel
       openid:
         title: Kevreañ gant OpenID
-        alt: Kevreañ gant un URL OpenID
+        alt: Logo OpenID
       google:
         title: Kevreañ gant Google
-        alt: Kevreañ gant OpenID Google
+        alt: Logo Google
       facebook:
         title: Kevreañ gant Facebook
-        alt: Kevreañ gant ur gont Facebook
+        alt: Logo Facebook
       microsoft:
         title: Kevreañ gant Microsoft
-        alt: Kevreañ gant ur gont Microsoft
+        alt: Logo Microsoft
       github:
         title: Kevreañ gant GitHub
-        alt: Kevreañ gant ur gont GitHub
+        alt: Logo GitHub
       wikipedia:
         title: Kevreañ gant Wikipedia
-        alt: Kevreañ gant ur gont Wikipedia
+        alt: Logo Wikipedia
   oauth:
     authorize:
       title: Aotren mont d'ho kont
@@ -2650,6 +2650,7 @@ br:
       terms accepted: Trugarez deoc'h evit bezañ asantet da ziferadennoù nevez ar
         c'henlabourer !
       email_help:
+        privacy_policy: Politikerezh prevezded
         html: Ho chomlec'h ne vo ket hewel d'an holl, sellit ouzh %{privacy_policy_link}
           evit gouzout hiroc'h.
       consider_pd: domani foran
@@ -2823,7 +2824,6 @@ br:
       show: Gwelet ar stankadur-mañ
       back: Gwelet an holl stankadurioù
     filter:
-      block_expired: Aet eo ar stankadur d'e dermen dija ha ne c'hall ket bezañ aozet.
       block_period: Ar prantad stankañ a rank bezañ unan eus an talvoudoù a c'haller
         dibab ar roll disac'hañ.
     create:
index 9eda7a4e87cc68e2842e53dbd1bea8af0cfc90de..fbb3aa7c76369ce04abb25a52ec672874085060a 100644 (file)
@@ -1471,7 +1471,6 @@ bs:
       show: Pogledati ovu blokadu
       back: Pogledati sve blokade
     filter:
-      block_expired: Blokada je već istekla i ne može se uređivati.
       block_period: Period blokade mora biti jedna od vrijednosti iz drop-down liste.
     create:
       flash: Napraviti blokadu na korisnika  %{name}.
index 6cd0f05c2983db47f51dfac04d77e2353f16ee95..eb1e7f6e9dacc27c2795065fadd89774cac25070 100644 (file)
@@ -2870,7 +2870,6 @@ ca:
       show: Mostra el bloc
       back: Mostra tots els blocs
     filter:
-      block_expired: El bloc ja ha expirat i no es pot editar.
       block_period: El període de blocatge ha de ser un dels valors seleccionables
         de la llista desplegable.
     create:
index 8d2d39ebf5a674d61d84f22393c3556d3762ac19..1fcecbf077223f603807ca16089b0a1284943f1e 100644 (file)
@@ -124,7 +124,7 @@ ce:
         longitude: Дохалла
         public: Массарна
         description: Цуьнах лаьцна
-        gpx_file: GPX файл чуяккха
+        gpx_file: GPX файл чуйаккха
         visibility: Гуш хилар
         tagstring: Тегаш
       message:
@@ -1618,6 +1618,7 @@ ce:
       коьрта белхаш дӀахьош долу дера.
     osm_read_only: OpenStreetMap база карарчу хенахь ешаран режимехь йу,база Ӏалашъяран
       белхаш дӀахьош долу дер.
+    nothing_to_preview: Хьалххе хьажа хӀумма а дац.
     donate: Дехар ду, гӀо де OpenStreetMap %{link} аппаратан фонда карлайоккхуш.
     help: ГӀо
     about: Проектах лаьцна
@@ -1663,13 +1664,19 @@ ce:
       befriend_them: Иштта %{befriendurl} чохь доттагӀ санна тӀетоха йиш йу хьан.
       befriend_them_html: Иштта %{befriendurl} чохь доттагӀ санна тӀетоха йиш йу хьан.
     gpx_description:
+      description_with_tags: 'Иза хьан GPX файлах тера йу %{trace_name} %{trace_description}
+        описаниеца а, хӀара тегашца а: %{tags}'
       description_with_tags_html: 'Иза хьан GPX файлах тера йу %{trace_name} %{trace_description}
         описаниеца а, хӀара тегашца а: %{tags}'
+      description_with_no_tags: Иза хьан GPX файлах тера йу %{trace_name} %%{trace_description}
+        дицарца, цхьа а тег йоцуш
       description_with_no_tags_html: Иза хьан GPX файлах тера йу %{trace_name} %%{trace_description}
         дицарца, цхьа а тег йоцуш
     gpx_failure:
       hi: Маршалла ду %{to_user},
       failed_to_import: 'импорт ян аьтто ца баьлла. Кхузахь гӀалат ду:'
+      more_info: GPX импортан кхачамбацарех лаьцна кхин а хаамаш каро йиш йу %{url}
+        тӀехь.
       more_info_html: GPX импортан кхачамбацарех лаьцна кхин а хаамаш каро йиш йу
         %{url} тӀехь.
       subject: '[OpenStreetMap] GPX Импорт ца хилира'
@@ -1679,6 +1686,8 @@ ce:
         one: кхиамца дӀатоьхна %{trace_points}хила тарлучу %{count} point. точках.
         other: loaded successfully with %{trace_points}хила тарлучу %{count} points.
           точках.
+      trace_location: Хьан лар лело йиш йу %{trace_url}
+      all_your_traces: Хьан йерриге а кхиамца чуйиллина GPX лараш каро йиш йу %{url}
       all_your_traces_html: Хьан ерриге а кхиамца чуйиллина GPX лараш каро йиш йу
         %{url} тӀехь.
       subject: '[OpenStreetMap] GPX  Импортан дика хилира'
@@ -1979,7 +1988,7 @@ ce:
       url: URL
       codeblock: Кодан блок
     richtext_field:
-      edit: Ð\9dиÑ\81йе
+      edit: Ð\9dиÑ\81йан
       preview: Хьажа
   site:
     about:
@@ -2263,11 +2272,11 @@ ce:
         description: Йукъаралло латтош йу болалуш болчарна хьехам.
       community:
         title: ГӀо а, йукъараллин форум а
-        description: OpenStreetMap-ах лаьцна гӀо лаха а, къамелаш дан а юкъара меттиг.
+        description: OpenStreetMap-ах лаьцна гӀо лаха а, къамелаш дан а йукъара меттиг.
       mailing_lists:
         title: Почтан тептарш
-        description: Хаттар ло йа дийцаре де оьшуш долу хаттарш,  шуьйрачу актуальни
-          йа регионан рассылкашкахь.
+        description: Хаттар ло йа дийцаре де оьшуш долу хаттарш, шуьйрачу актуалан
+          йа регионан дIасатасаршкахь.
       irc:
         title: IRC
         description: Интерактивни чат тайп-тайпанчу меттанашкахь а, дуккха а теманашца
@@ -2517,7 +2526,7 @@ ce:
       start_coordinates: 'Координатийн йуьхь:'
       coordinates_html: '%{latitude}; %{longitude}'
       map: карта
-      edit: Ð½Ð¸Ñ\81йе
+      edit: Ð½Ð¸Ñ\81йан
       owner: 'Йерг:'
       description: 'Цуьнах лаьцна:'
       tags: 'Тегаш:'
@@ -2659,6 +2668,8 @@ ce:
       write_notes: заметкаш хийца
       write_redactions: Картан хаамаш хийца
       read_email: Декъашхочун электронан почтан адрес деша
+      consume_messages: Деша, статус карлайаккха, лелончан хаамаш дӀабаха
+      send_messages: Кхечу лелочаьрга леррина хаамаш дӀакхачо
       skip_authorization: Автоматически дӀахьедар тӀечӀагӀдар
     for_roles:
       moderator: ХӀара бакъо лерина йу модераторшна бен лело йиш йоцучу гӀуллакхашна
@@ -2714,15 +2725,15 @@ ce:
       name: ЦӀе
       permissions: Магор
     application:
-      edit: Ð\9dиÑ\81йе
+      edit: Ð\9dиÑ\81йан
       delete: ДӀайаккха
       confirm_delete: ХIар приложени дӀайаккха?
     new:
       title: Регистаци е керла приложенина
     edit:
-      title: Ð\9dиÑ\81йе Ñ\85Ñ\8cан Ð¿Ñ\80иложени
+      title: Ð¥Ñ\8cан Ð¿Ñ\80иложени Ð½Ð¸Ñ\81йан
     show:
-      edit: Ð\9dиÑ\81йе
+      edit: Ð\9dиÑ\81йан
       delete: ДӀайаккха
       confirm_delete: ХIар приложени дӀайаккха?
       client_id: Клиентан ID
@@ -2804,7 +2815,7 @@ ce:
         а, тӀаккха ши байракха а гIоттайай, «ДӀадахьа» нуьйда тӀе тӀаIайе
       contributor_terms_explain: ХӀокху барто леладо хьан хӀинцалера а, хиндолчу а
         дакъалацаран хьелаш.
-      read_ct: Ас ешна а, реза а ву лакхахь хьахийначу хьолана.
+      read_ct: Ð\90Ñ\81 Ð¹ÐµÑ\88на Ð°, Ñ\80еза Ð° Ð²Ñ\83 Ð»Ð°ÐºÑ\85аÑ\85Ñ\8c Ñ\85Ñ\8cаÑ\85ийнаÑ\87Ñ\83 Ñ\85Ñ\8cолана.
       tou_explain_html: '%{tou_link} урхалла до веб-сайтан а, OSMF-о луш йолчу кхечу
         инфраструктуран а. Дехар ду, ссылка тӀе а таӀийна, хьажа текстана тIех долчунна.'
       read_tou: Со реза ву Лелоран хьолашна
@@ -2975,12 +2986,13 @@ ce:
       show: ХӀокху блоке хьажа
       back: Гайта дерриге блоктохарш
     filter:
-      block_expired: Блок хӀинцале чекхъяьлла,йа и хийца йиш яц.
       block_period: Блокировкан мур хила беза цхьаъ маьIан долуш тептарчура хаьржина.
     create:
       flash: Декъашхочунна %{name} тӀехь блок кхоьллина .
     update:
       only_creator_can_edit: И блок кхоьллинчу модераторан бен хийца йиш яц.
+      only_creator_or_revoker_can_edit: ХӀара блок кхоьллинчу йа йухайаьккхинчу модераторийн
+        бен хийца йиш йац.
       success: Блок карлайаккхина.
     index:
       title: Декъашхочун блоктохар
@@ -3291,6 +3303,8 @@ ce:
           агӀора
         onramp_left_without_directions: Аьрру агӀор дӀаверза
         onramp_left: Аьрру агӀор дӀаверза
+        endofroad_left_without_exit: Некъ чаккхаболучех аьрру агӀор дӀаверза %{name}
+          тӀе.
         merge_left_without_exit: Аьрру агӀор вала %{name} тIе
         fork_left_without_exit: ГӀонжагӀехь аьрру агӀор дӀаверза %{name} тӀе.
         slight_left_without_exit: '%{name} тӀе аьрру агӀор меллаш дӀаверза'
@@ -3338,7 +3352,7 @@ ce:
   redactions:
     edit:
       heading: Нисйе редакци
-      title: Ð\9dиÑ\81йе Ñ\80едакÑ\86и
+      title: Ð ÐµÐ´Ð°ÐºÑ\86и Ð½Ð¸Ñ\81йан
     index:
       empty: Гайта цхьа а редакци яц.
       heading: Редакцин тептар
index bacaa1ede5ef0c22383261844ad5180e3707d4d6..f284caefc24eb61eccc27b1f5e917e2ce2b40836 100644 (file)
@@ -707,6 +707,8 @@ cs:
       comment: Komentář
       newer_comments: Novější komentáře
       older_comments: Starší komentáře
+    new:
+      heading: Přidat komentář do následující diskuse k deníkovému záznamu?
   doorkeeper:
     errors:
       messages:
@@ -745,6 +747,10 @@ cs:
       contact_the_community_html: Neváhejte %{contact_link} komunitu OpenStreetMap,
         pokud jste našli nefunkční odkaz / chybu. Poznamenejte si přesnou adresu URL
         vašeho požadavku.
+    bad_request:
+      title: Chybný požadavek
+      description: Operace, kterou jste žádali po serveru OpenStreetMap, není platná
+        (HTTP 400)
     forbidden:
       title: Zakázáno
       description: Operace, kterou jste požadovali na serveru OpenStreetMap, je dostupná
@@ -941,6 +947,7 @@ cs:
           college: Budova školy
           commercial: Komerční budova
           construction: Budova ve výstavbě
+          cowshed: Kravín
           detached: Rodinný dům
           dormitory: Kolej
           duplex: Dvojdomek
@@ -970,6 +977,7 @@ cs:
           shed: Kůlna
           stable: Stáj
           static_caravan: Karavan
+          sty: Vepřín
           temple: Budova chrámu
           terrace: Terasovitá budova
           train_station: Železniční stanice
@@ -1820,8 +1828,8 @@ cs:
           Poznámka je umístěna poblíž %{place}.'
         commented_note_html: '%{commenter} reaktivoval poznámku k mapě, kterou jste
           komentovali. Poznámka je umístěna poblíž %{place}.'
-      details: Podrobnosti k poznámce můžete najít na %{url}.
-      details_html: Podrobnosti k poznámce můžete najít na %{url}.
+      details: Odpovědět nebo se dozvědět více o této poznámce můžete na %{url}.
+      details_html: Odpovědět nebo se dozvědět více o této poznámce můžete na %{url}.
     changeset_comment_notification:
       description: 'Sada změn OpenStreetMap #%{id}'
       hi: Dobrý den, uživateli %{to_user},
@@ -1842,8 +1850,8 @@ cs:
         partial_changeset_with_comment: s komentářem „%{changeset_comment}“
         partial_changeset_with_comment_html: s komentářem „%{changeset_comment}“
         partial_changeset_without_comment: bez komentáře
-      details: Více informací o této sadě změn lze nalézt na %{url}.
-      details_html: Odpovězte nebo se zjistěte více o změnách na %{url}.
+      details: Odpovědět nebo se dozvědět více o této sadě změn můžete na %{url}.
+      details_html: Odpovědět nebo se dozvědět více o této sadě změn můžete na %{url}.
       unsubscribe: Od aktualizací této sady změn se můžete odhlásit na %{url}.
       unsubscribe_html: Od aktualizací této sady změn se můžete odhlásit na %{url}.
   confirmations:
@@ -2670,7 +2678,7 @@ cs:
         other: GPX soubor s %{count} body od uživatele %{user}
       description_without_count: GPX soubor od uživatele %{user}
   application:
-    basic_auth_disabled: 'HTTP základní autentifikace je zakázaná: %{link}'
+    basic_auth_disabled: 'HTTP Basic autentizace je zakázaná: %{link}'
     oauth_10a_disabled: 'OAuth 1.0 a 1.0a jsou zakázané: %{link}'
     permission_denied: Pro přístup k této akci nemáte oprávnění
     require_cookies:
@@ -2697,22 +2705,22 @@ cs:
       openid_login_button: Pokračovat
       openid:
         title: Přihlásit se pomocí OpenID
-        alt: OpenID Logo
+        alt: Logo OpenID
       google:
         title: Přihlásit se prostřednictvím Google
-        alt: Google Logo
+        alt: Logo Googlu
       facebook:
         title: Přihlásit se přes Facebook
-        alt: Facebook logo
+        alt: Logo Facebooku
       microsoft:
         title: Přihlásit se přes Microsoft
-        alt: Microsoft Logo
+        alt: Logo Microsoftu
       github:
         title: Přihlásit se přes GitHub
-        alt: GitHub Logo
+        alt: Logo GitHubu
       wikipedia:
         title: Přihlásit se účtem na Wikipedii
-        alt: Wikipedia Logo
+        alt: Logo Wikipedie
   oauth:
     authorize:
       title: Autorizovat přístup k vašemu účtu
@@ -2881,7 +2889,7 @@ cs:
       continue: Zaregistrovat se
       terms accepted: Děkujeme za odsouhlasení nových podmínek pro přispěvatele!
       email_help:
-        privacy_policy: Zásady ochrany osobních údajů
+        privacy_policy: pravidly ochrany osobních údajů
         privacy_policy_title: Pravidla ochrany osobních údajů OSMF, včetně části o
           e-mailových adresách
         html: Vaše adresa se nezobrazuje veřejně, více informací získáte na stránce
@@ -3069,7 +3077,6 @@ cs:
       show: Zobrazit tento blok
       back: Zobrazit všechny bloky
     filter:
-      block_expired: Tento blok již vypršel, a proto ho nelze upravovat.
       block_period: Doba bloku musí být jedna z těch, které obsahuje rozevírací seznam.
     create:
       flash: Uživatel %{name} zablokován.
@@ -3246,8 +3253,10 @@ cs:
       intro: Zahlédli jste chybu nebo prázdné místo? Dejte vědět ostatním uživatelům,
         aby to mohli napravit. Posuňte značku na správné místo a napište poznámku
         vysvětlující problém.
-      anonymous_warning_log_in: Přihlásit se
-      anonymous_warning_sign_up: Zaregistrovat se
+      anonymous_warning_html: Nejste přihlášeni. Pokud chcete získávat aktualizace
+        k vaší poznámce, %{log_in} nebo %{sign_up}.
+      anonymous_warning_log_in: přihlaste se
+      anonymous_warning_sign_up: se zaregistrujte
       advice: Vaše poznámka je veřejná a může sloužit k úpravám mapy, proto nevkládejte
         žádné osobní údaje ani informace z autorskoprávně chráněných map či adresářů.
       add: Přidat poznámku
@@ -3265,14 +3274,15 @@ cs:
       custom_dimensions: Nastavit vlastní rozměry
       format: 'Formát:'
       scale: 'Měřítko:'
-      image_dimensions: Obrázek bude ukazovat standardní vrstvu v %{width} × %{height}
+      image_dimensions: Obrázek bude ukazovat vrstvu %{layer} v %{width} × %{height}
       download: Stáhnout
       short_url: Krátké URL
       include_marker: Vložit značku
       center_marker: Vycentrovat mapu na značku
       paste_html: HTML ke vložení na webovou stránku
       view_larger_map: Zobrazit větší mapu
-      only_standard_layer: Jako obrázek lze exportovat jen standardní vrstvu
+      only_standard_layer: Jako obrázek lze exportovat jen vrstvy Standardní, Cyklomapa
+        a Dopravní
     embed:
       report_problem: Nahlásit problém
     key:
index 08de0e7671f20b285b2f2fa6006e178b30f06eb1..4f1cd9229fee01c061f55b18a0d194e6709788ee 100644 (file)
@@ -438,8 +438,8 @@ cy:
         way: llwybr
         relation: perthynas
     start_rjs:
-      feature_warning: Wrthi'n llwytho %{num_features} nodwedd, a all arafu eich porwr.
-        Ydych chi wir eisiau gweld y data?
+      feature_warning: Wrthi'n llwytho %{num_features} nodwedd, a all arafu neu chwalu
+        eich porwr. Ydych chi wir eisiau gweld y data?
       load_data: Llwytho data
       loading: Wrthi'n llwytho...
     tag_details:
@@ -458,9 +458,15 @@ cy:
       introduction: Cliciwch ar y map i ddarganfod nodweddion gerllaw.
       nearby: Nodweddion gerllaw
       enclosing: Nodweddion amgáu
+  old_nodes:
+    not_found:
+      sorry: 'Sori, ni ellir canfod fersiwn %{version} o''r nod #%{id}.'
   old_ways:
     not_found:
       sorry: 'Sori, ni ellir canfod fersiwn %{version} o lwybr #%{id}.'
+  old_relations:
+    not_found:
+      sorry: 'Sori, ni ellir canfod fersiwn %{version} o''r perthynas #%{id}.'
   changesets:
     changeset_paging_nav:
       showing_page: Tudalen %{page}
index 8f9f1adaa6e6447924f325d5c13cfd8677a1c71d..fe20af61a8364f765b36a3286b0e9e518e1310a9 100644 (file)
@@ -1646,6 +1646,7 @@ da:
       databasevedligeholdelse.
     osm_read_only: OpenStreetMap databasen er for øjeblikket ikke redigerbar på grund
       af database vedligeholdelse.
+    nothing_to_preview: Intet at forhåndsvise
     donate: Støt OpenStreetMap med en %{link} til Hardware-upgradefonden.
     help: Hjælp
     about: Om
@@ -2698,6 +2699,8 @@ da:
       write_notes: Ændre bemærkninger
       write_redactions: Rediger kortdata
       read_email: Læse brugerens e-mailadresse
+      consume_messages: Læs, opdater status og slet brugerbeskeder
+      send_messages: Send private beskeder til andre brugere
       skip_authorization: Godkend applikation automatisk
     for_roles:
       moderator: Denne tilladelse er til handlinger, der kun er tilgængelige for moderatorer
@@ -3015,7 +3018,6 @@ da:
       show: Vis denne blokering
       back: Vis alle blokeringer
     filter:
-      block_expired: Blokeringen er allerede udløbet og kan ikke redigeres.
       block_period: Blokeringsperioden skal være en af de værdier der er valgbar i
         listen over værdier.
     create:
@@ -3023,6 +3025,8 @@ da:
     update:
       only_creator_can_edit: Kun moderatoren som oprettede denne blokering kan ændre
         den.
+      only_creator_or_revoker_can_edit: Kun de moderatorer, der har oprettet eller
+        ophævet denne blokering, kan redigere den.
       success: Blokering opdateret.
     index:
       title: Brugerblokeringer
@@ -3203,14 +3207,15 @@ da:
       custom_dimensions: Angiv brugerdefinerede dimensioner
       format: 'Format:'
       scale: 'Skala:'
-      image_dimensions: Billedet vil vise standardlaget i %{width} x %{height}
+      image_dimensions: Billedet vil vise laget %{layer} i %{width} x %{height}
       download: Hent
       short_url: Kort URL
       include_marker: Tilføj markør
       center_marker: Centrér kortet på markøren
       paste_html: Indsæt HTML som skal indlejres i websiden
       view_larger_map: Vis større kort
-      only_standard_layer: Kun standardlaget kan eksporteres som et billede
+      only_standard_layer: Kun lagene standard, cykelkort og transport kan eksporteres
+        som et billede
     embed:
       report_problem: Rapporter et problem
     key:
index 681c0dec35834df0107fe0ef160fdaebe8407e38..171efd3f8d1d474d44f71d1710b1a965523d0412 100644 (file)
@@ -1737,6 +1737,7 @@ de:
       nicht verfügbar.
     osm_read_only: Die OpenStreetMap-Datenbank ist im Moment wegen wichtiger Wartungsarbeiten
       im „Nur-Lesen-Modus“.
+    nothing_to_preview: Es gibt keine Vorschau.
     donate: Unterstütze die OpenStreetMap-Hardwarespendenaktion durch eine eigene
       %{link}.
     help: Hilfe
@@ -1788,13 +1789,19 @@ de:
       befriend_them: Du kannst sie/ihn unter %{befriendurl} ebenfalls als Freund hinzufügen.
       befriend_them_html: Du kannst sie/ihn unter %{befriendurl} auch als Freund hinzufügen.
     gpx_description:
+      description_with_tags: 'Es sieht so aus, als ob deine GPX-Datei %{trace_name}
+        mit der Beschreibung %{trace_description} und den folgenden Tags: %{tags}'
       description_with_tags_html: 'Es scheint, dass deine GPX-Datei %{trace_name}
         mit der Beschreibung %{trace_description} und den folgenden Tags: %{tags}'
+      description_with_no_tags: Es sieht so aus, als ob deine GPX-Datei %{trace_name}
+        mit der Beschreibung %{trace_description} und ohne Tags
       description_with_no_tags_html: Es scheint, dass deine GPX-Datei %{trace_name}
         mit der Beschreibung %{trace_description} und ohne Tags
     gpx_failure:
       hi: Hallo %{to_user},
       failed_to_import: 'konnte nicht importiert werden, die Fehlermeldung:'
+      more_info: Weitere Informationen über Fehler bei GPX-Importen und wie sie vermieden
+        werden können finden sich in %{url}
       more_info_html: Weitere Informationen über Fehler bei GPX-Importen und wie sie
         vermieden werden können finden sich in %{url}
       import_failures_url: https://wiki.openstreetmap.org/wiki/DE:GPX#Warum_wurde_meine_GPX-Datei_nicht_richtig_hochgeladen.3F
@@ -1804,6 +1811,9 @@ de:
       loaded:
         one: mit %{trace_points} von einem möglichen Punkt erfolgreich geladen.
         other: mit %{trace_points} von %{count} möglichen Punkten erfolgreich geladen.
+      trace_location: Dein Track ist verfügbar unter %{trace_url}
+      all_your_traces: Alle deine erfolgreich hochgeladenen GPX-Tracks findest du
+        unter %{url}.
       all_your_traces_html: Alle deine erfolgreich hochgeladenen GPX-Traces findest
         du unter %{url}.
       subject: '[OpenStreetMap] GPX-Import erfolgreich'
@@ -2840,6 +2850,8 @@ de:
       write_notes: Notizen bearbeiten
       write_redactions: Kartendaten redigieren
       read_email: Lesen der Benutzer-E-Mail-Adresse
+      consume_messages: Lesen, Aktualisieren des Status und Löschen von Benutzernachrichten
+      send_messages: Private Nachrichten an andere Benutzer senden
       skip_authorization: Antrag automatisch genehmigen
     for_roles:
       moderator: Diese Berechtigung gilt nur für Aktionen, die nur Moderatoren zur
@@ -3173,14 +3185,14 @@ de:
       show: Diese Sperre anzeigen
       back: Alle Sperren anzeigen
     filter:
-      block_expired: Die Sperre kann nicht bearbeitet werden, da die Sperrdauer bereits
-        abgelaufen ist.
       block_period: Die Sperrdauer muss einem der Werte aus der Drop-Down-Liste entsprechen.
     create:
       flash: Benutzer %{name} wurde gesperrt.
     update:
       only_creator_can_edit: Nur der Moderator, der die Sperre eingerichtet hat, kann
         sie ändern.
+      only_creator_or_revoker_can_edit: Nur die Moderatoren, die die Sperre eingerichtet
+        haben, können sie ändern.
       success: Sperre aktualisiert.
     index:
       title: Benutzersperren
index e7a1d3508af6c576eecc4ff12636a5d78bc839ed..b08248f3c7b2392bb5eec2b584ba44f00b7553c6 100644 (file)
@@ -1623,7 +1623,6 @@ dsb:
       show: Toś to blokěrowanje pokazaś
       back: Wšykne blokěrowanja pokazaś
     filter:
-      block_expired: Blokěrowanje jo južo pśepadnuło a njedajo se wobźěłaś.
       block_period: Cas blokěrowanja musy jadna z gódnotow byś, kótarež daju se z
         padajuceje lisćiny wubraś.
     create:
index ef3f2c0b2359be5d6c37d23a257ab2405f33c165..38d191b11c48b4ffe0726734af0027b30cbcf9f7 100644 (file)
@@ -677,6 +677,9 @@ el:
       comment: Σχόλιο
       newer_comments: Νεότερα σχόλια
       older_comments: Παλαιότερα σχόλια
+    new:
+      heading: Να προσθέσετε ένα σχόλιο στην ακόλοουθη συζήτηση για την καταχώριση
+        ημερολογίου;
   doorkeeper:
     errors:
       messages:
@@ -922,6 +925,7 @@ el:
           college: Πανεπιστημιακό κτήριο
           commercial: Εμπορικό κτήριο
           construction: Κτήριο υπό κατασκευή
+          cowshed: Αγελαδοστάσιο
           detached: Μεζονέτα
           dormitory: Κοιτώνας
           duplex: Μεζονέτα
@@ -951,6 +955,7 @@ el:
           shed: Υπόστεγο
           stable: Στάβλος
           static_caravan: Τροχόσπιτο
+          sty: Χοιροστάσιο
           temple: Κτήριο ναού
           terrace: Σειρά όμοιων σπιτιών
           train_station: Κτήριο Σιδηροδρομικού Σταθμού
@@ -1670,6 +1675,7 @@ el:
       λόγω εργασιών συντήρησης.
     osm_read_only: Η βάση δεδομένων του OpenStreetMap έχει τεθεί προσωρινά σε λειτουργία
       «μόνο για ανάγνωση» λόγω εργασιών συντήρησης.
+    nothing_to_preview: Τίποτα για προεπισκόπηση.
     donate: Υποστηρίξτε το OpenStreetMap %{link} στον έρανο αναβάθμισης υλικού.
     help: Βοήθεια
     about: Σχετικά
@@ -1718,13 +1724,19 @@ el:
       befriend_them: Μπορείτε επίσης να τους προσθέσετε ως φίλους στο %{befriendurl}.
       befriend_them_html: Μπορείτε επίσης να τους προσθέσετε ως φίλους στο %{befriendurl}.
     gpx_description:
+      description_with_tags: 'Φαίνεται πως το αρχείο σας GPX %{trace_name} με την
+        περιγραφή %{trace_description} και με τις παρακάτω ετικέτες: %{tags}'
       description_with_tags_html: 'Φαίνεται πως το αρχείο σου GPX %{trace_name} με
         την περιγραφή %{trace_description} και με τις παρακάτω ετικέτες: %{tags}'
+      description_with_no_tags: Φαίνεται πως το αρχείο σας GPX %{trace_name} με την
+        περιγραφή %{trace_description} και χωρίς ετικέτες
       description_with_no_tags_html: Φαίνεται πως το αρχείο σου GPX %{trace_name}
         με την περιγραφή %{trace_description} και χωρίς ετικέτες
     gpx_failure:
       hi: Γεια σας %{to_user},
       failed_to_import: 'Απέτυχε η εισαγωγή. Το σφάλμα είναι:'
+      more_info: Περισσότερες πληροφορίες σχετικά με τα σφάλματα εισαγωγής GPX και
+        πως να τα αποφύγετε, μπορείτε να βρείτε στο %{url}.
       more_info_html: Περισσότερες πληροφορίες σχετικά με τις αποτυχίες εισαγωγής
         GPX και τον τρόπο αποφυγής τους μπορείτε να βρείτε στη διεύθυνση %{url}.
       subject: '[OpenStreetMap] Η εισαγωγή GPX απέτυχε'
@@ -1733,6 +1745,9 @@ el:
       loaded:
         one: φορτώθηκε επιτυχώς με %{trace_points} από πιθανό %{count} σημείο.
         other: φορτώθηκε επιτυχώς με %{trace_points} από πιθανά %{count} σημεία.
+      trace_location: Το ίχνος σας είναι διαθέσιμο στο %{trace_url}
+      all_your_traces: Όλα τα επιτυχώς ανεβασμένα ίχνη GPX σας μπορούν να βρεθούν
+        στο %{url}
       all_your_traces_html: Όλα τα ίχνη GPX που ανεβάσατε με επιτυχία μπορούν να βρεθούν
         στη διεύθυνση %{url}.
       subject: '[OpenStreetMap] Η εισαγωγή GPX πέτυχε'
@@ -2654,25 +2669,26 @@ el:
       oauth2_authorizations: Εξουσιοδοτήσεις OAuth 2
       muted_users: Χρήστες σε Σίγαση
     auth_providers:
+      openid_url: OpenID URL
       openid_login_button: Συνέχεια
       openid:
         title: Σύνδεση με OpenID
-        alt: Î£Ï\8dνδεÏ\83η Î¼Îµ Î­Î½Î± OpenID URL
+        alt: Î\9bογÏ\8cÏ\84Ï\85Ï\80ο OpenID
       google:
         title: Σύνδεση με Google
-        alt: Î£Ï\8dνδεÏ\83η Î¼Îµ Î­Î½Î± Google OpenID
+        alt: Î\9bογÏ\8cÏ\84Ï\85Ï\80ο Google
       facebook:
         title: Σύνδεση με Facebook
-        alt: Î£Ï\8dνδεÏ\83η Î¼Îµ Î»Î¿Î³Î±Ï\81ιαÏ\83μÏ\8c Facebook
+        alt: Î\9bογÏ\8cÏ\84Ï\85Ï\80ο Facebook
       microsoft:
         title: Σύνδεση με Microsoft
-        alt: Î£Ï\8dνδεÏ\83η Î¼Îµ Î»Î¿Î³Î±Ï\81ιαÏ\83μÏ\8c Microsoft
+        alt: Î\9bογÏ\8cÏ\84Ï\85Ï\80ο Microsoft
       github:
         title: Σύνδεση με GitHub
-        alt: Î£Ï\8dνδεÏ\83η Î¼Îµ Î»Î¿Î³Î±Ï\81ιαÏ\83μÏ\8c GitHub
+        alt: Î\9bογÏ\8cÏ\84Ï\85Ï\80ο GitHub
       wikipedia:
         title: Σύνδεση με Wikipedia
-        alt: Î£Ï\85νδεθείÏ\84ε Î¼Îµ Î»Î¿Î³Î±Ï\81ιαÏ\83μÏ\8c Wikipedia
+        alt: Î\9bογÏ\8cÏ\84Ï\85Ï\80ο Wikipedia
   oauth:
     authorize:
       title: Επιτρέψτε την πρόσβαση στο λογαριασμό σας
@@ -2714,7 +2730,12 @@ el:
       write_notes: Τροποποίηση σημειώσεων
       write_redactions: Αφαίρεση και απόκρυψη δεδομένων χάρτη
       read_email: Διαβάζει τη διεύθυνση email χρήστη
+      consume_messages: Ανάγνωση, ενημέρωση της κατάστασης και διαγραφή των μηνυμάτων
+        χρήστη
+      send_messages: Αποστολή προσωπικών μηνυμάτων σε άλλους χρήστες.
       skip_authorization: Αυτόματη έγκριση εφαρμογής
+    for_roles:
+      moderator: Αυτή η άδεια είναι για ενέργειες διαθέσιμες μόνο στους διαχειριστές
   oauth_clients:
     new:
       title: Καταχώρηση νέας εφαρμογής
@@ -2825,18 +2846,27 @@ el:
           το διορθώσει, να ενημερώσει, να το κατεβάσει και να το χρησιμοποιήσει.
         paragraph_2: Εγγραφείτε για να ξεκινήσετε να συνεισφέρετε.
         welcome: Καλώς ήλθατε στο OpenStreetMap
+      duplicate_social_email: Εάν έχετε ήδη λογαριασμό OpenStreetMap και επιθυμείτε
+        να χρησιμοποιείτε έναν πάροχο ταυτότητας τρίτου μέρους, παρακαλούμε να συνδεθείτε
+        χρησιμοποιώντας τον κωδικό πρόσβασής σας και να τροποποιήσετε τις ρυθμίσεις
+        του λογαριασμού σας.
       display name description: Το δημόσια εμφανιζόμενο όνομα χρήστη. Μπορείτε να
         το αλλάξετε αργότερα από τις προτιμήσεις.
       by_signing_up:
+        html: Με την εγγραφή σας, συμφωνείτε στους %{tou_link}, στην %{privacy_policy_link}
+          και στους %{contributor_terms_link}.
         privacy_policy: πολιτική απορρήτου
         privacy_policy_title: Πολιτική απορρήτου OSMF, συμπεριλαμβανομένης της ενότητας
           για τις διευθύνσεις ηλεκτρονικού ταχυδρομείου
         contributor_terms: όρους συνεισφοράς
-      tou: όροι χρήσης
+      tou: όρους χρήσης
       external auth: 'Έλεγχος ταυτότητας από τρίτο μέρος:'
       continue: Εγγραφή
       terms accepted: Ευχαριστούμε για την αποδοχή των νέων όρων συνεισφοράς!
       email_help:
+        privacy_policy: πολιτική απορρήτου
+        privacy_policy_title: Πολιτική απορρήτου OSMF, συμπεριλαμβανομένης της ενότητας
+          για τις διευθύνσεις ηλεκτρονικού ταχυδρομείου
         html: Η διεύθυνσή σας δεν εμφανίζεται δημόσια, ανατρέξτε στην %{privacy_policy_link}
           για περισσότερες πληροφορίες.
       consider_pd_html: Θεωρώ τις συνεισφορές μου να είναι στο %{consider_pd_link}.
@@ -3027,7 +3057,6 @@ el:
       show: Προβολή αυτής της φραγής
       back: Προβολή όλων των φραγών
     filter:
-      block_expired: Η φραγή έχει ήδη λήξει και δεν μπορεί να αλλάξει.
       block_period: Η περίοδος φραγής πρέπει να είναι μία από τις τιμές στην πτυσσόμενη
         λίστα.
     create:
@@ -3035,6 +3064,8 @@ el:
     update:
       only_creator_can_edit: Μόνο ο συντονιστής που δημιούργησε αυτήν τη φραγή μπορεί
         να την επεξεργαστεί.
+      only_creator_or_revoker_can_edit: Μόνο οι διαχειριστές που δημιούργησαν ή ανακαλέσαν
+        αυτή τη φραγή μπορούν να την επεξεργαστούν.
       success: Η φραγή ενημερώθηκε.
     index:
       title: Φραγές χρήστη
@@ -3217,7 +3248,7 @@ el:
       custom_dimensions: Ορισμός προσαρμοσμένων διαστάσεων
       format: 'Μορφή:'
       scale: 'Κλίμακα:'
-      image_dimensions: Η εικόνα θα εμφανίζει το τυπικό στρώμα στο %{width} x %{height}
+      image_dimensions: Η εικόνα θα εμφανίζει το %{layer} στο %{width} x %{height}
       download: Λήψη
       short_url: Σύντομος Σύνδεμος
       include_marker: Συμπερίληψη δείκτη
index 9850467f2f26cea4250ef0aef13e6814c25df25f..73e8191bdae7719463aedd32d1243d987110c895 100644 (file)
@@ -1936,7 +1936,6 @@ en-GB:
       show: View this block
       back: View all blocks
     filter:
-      block_expired: The block has already expired and cannot be edited.
       block_period: The blocking period must be one of the values selectable in the
         drop-down list.
     create:
index 2b83fec1f9d4097cb4e8036f1e2cc8314fe3bd47..a694163377f100a3c3a89261d07d1d8ad0a3ecb1 100644 (file)
@@ -1586,6 +1586,7 @@ en:
     tou: "Terms of Use"
     osm_offline: "The OpenStreetMap database is currently offline while essential database maintenance work is carried out."
     osm_read_only: "The OpenStreetMap database is currently in read-only mode while essential database maintenance work is carried out."
+    nothing_to_preview: "Nothing to preview."
     donate: "Support OpenStreetMap by %{link} to the Hardware Upgrade Fund."
     help: Help
     about: About
@@ -1626,11 +1627,14 @@ en:
       befriend_them: "You can also add them as a friend at %{befriendurl}."
       befriend_them_html: "You can also add them as a friend at %{befriendurl}."
     gpx_description:
+      description_with_tags: "It looks like your GPX file %{trace_name} with the description %{trace_description} and the following tags: %{tags}"
       description_with_tags_html: "It looks like your GPX file %{trace_name} with the description %{trace_description} and the following tags: %{tags}"
+      description_with_no_tags: "It looks like your GPX file %{trace_name} with the description %{trace_description} and no tags"
       description_with_no_tags_html: "It looks like your GPX file %{trace_name} with the description %{trace_description} and no tags"
     gpx_failure:
       hi: "Hi %{to_user},"
       failed_to_import: "failed to import. Here is the error:"
+      more_info: "More information about GPX import failures and how to avoid them can be found at %{url}."
       more_info_html: "More information about GPX import failures and how to avoid them can be found at %{url}."
       import_failures_url: "https://wiki.openstreetmap.org/wiki/GPX_Import_Failures"
       subject: "[OpenStreetMap] GPX Import failure"
@@ -1639,6 +1643,8 @@ en:
       loaded:
         one: "loaded successfully with %{trace_points} out of a possible %{count} point."
         other: "loaded successfully with %{trace_points} out of a possible %{count} points."
+      trace_location: "Your trace is available at %{trace_url}"
+      all_your_traces: "All your successfully uploaded GPX traces can be found at %{url}"
       all_your_traces_html: "All your successfully uploaded GPX traces can be found at %{url}."
       subject: "[OpenStreetMap] GPX Import success"
     signup_confirm:
@@ -2641,6 +2647,8 @@ en:
       write_notes: Modify notes
       write_redactions: Redact map data
       read_email: Read user email address
+      consume_messages: Read, update status and delete user messages
+      send_messages: Send private messages to other users
       skip_authorization: Auto approve application
     for_roles:
       moderator: This permission is for actions available only to moderators
@@ -2940,6 +2948,7 @@ en:
       flash: "Created a block on user %{name}."
     update:
       only_creator_can_edit: "Only the moderator who created this block can edit it."
+      only_creator_or_revoker_can_edit: "Only the moderators who created or revoked this block can edit it."
       success: "Block updated."
     index:
       title: "User blocks"
index 8c509274a516b7b95b085fb67959f3140ef5328b..66296e847f9c4e00476bc12786c9ce78b5e951db 100644 (file)
@@ -1631,6 +1631,7 @@ eo:
       laboroj de prizorgado.
     osm_read_only: La OpenStreetMap-datumbazo estas nuntempe nurlega pro necesaj laboroj
       de prizorgado.
+    nothing_to_preview: Nenio por antaŭvidi.
     donate: Subteni OpenStreetMap %{link} al fonduso por modernigi aparataron.
     help: Helpo
     about: Pri
@@ -1678,13 +1679,18 @@ eo:
       befriend_them: Vi ankaŭ povas aldoni vin kiel amikon ĉe %{befriendurl}.
       befriend_them_html: Vi ankaŭ povas aldoni ilin kiel amiko ĉe %{befriendurl}
     gpx_description:
+      description_with_tags: 'Ŝajnas, ke tio ĉi estas via GPX‑dosiero %{trace_name}
+        kun la priskribo %{trace_description} kaj kun la jenaj etikedoj: %{tags}'
       description_with_tags_html: 'Ŝajnas, ke tio ĉi estas via GPX‑dosiero %{trace_name}
         kun la priskribo %{trace_description} kaj kun la jenaj etikedoj: %{tags}'
+      description_with_no_tags: Ŝajnas, ke tio ĉi estas via GPX‑dosiero %{trace_name}
+        kun la priskribo %{trace_description} kaj sen etikedoj
       description_with_no_tags_html: Ŝajnas, ke tio ĉi estas via GPX‑dosiero %{trace_name}
         kun la priskribo %{trace_description} kaj sen etikedoj
     gpx_failure:
       hi: Saluton %{to_user},
       failed_to_import: 'ne estas enportita sukcese. Eraro:'
+      more_info: Pliaj informoj pri eraroj dum enporti GPX‑dosierojn troviĝas ĉe %{url}.
       more_info_html: Pliaj informoj pri eraroj dum enporti GPX‑dosierojn troviĝas
         ĉe %{url}.
       subject: '[OpenStreetMap] Eraro dum enportado de GPX-dosiero'
@@ -1693,6 +1699,8 @@ eo:
       loaded:
         one: estas sukcese enlegita kun %{trace_points} el ebla %{count} punkto.
         other: estas sukcese enlegita kun %{trace_points} el eblaj %{count} punktoj.
+      trace_location: Via spuro estas disponebla ĉe %{trace_url}
+      all_your_traces: Ĉiuj viaj sukcese alŝutitaj GPX-spuroj troveblas ĉe %{url}
       all_your_traces_html: Ĉiuj viaj sukcese alŝutitaj GPX-spuroj troveblas ĉe %{url}.
       subject: '[OpenStreetMap] GPX-dosiero enportita sukcese'
     signup_confirm:
@@ -2660,6 +2668,8 @@ eo:
       write_notes: modifi rimarkojn
       write_redactions: Redakti map-datumojn
       read_email: legi retpoŝtan adreson de uzanto
+      consume_messages: legi, ŝanĝi staton kaj forigi mesaĝojn de uzanto
+      send_messages: sendi privatajn mesaĝojn al aliaj uzantoj
       skip_authorization: Aŭtomate akcepti aplikaĵojn
     for_roles:
       moderator: Tiu ĉi permeso estas por agoj disponeblaj nur por kontrolantoj
@@ -2973,13 +2983,14 @@ eo:
       show: Montri ĉi tiun blokadon
       back: Montri ĉiujn blokadojn
     filter:
-      block_expired: Ĉi tiu blokado malvalidiĝis kaj neredakteblas.
       block_period: La periodo de blokado estu unu el la valoroj elektitaj el la fallisto.
     create:
       flash: Kreis blokon por uzanto %{name}.
     update:
       only_creator_can_edit: Nur la kontrolanto kiu kreis ĉi tiun blokadon, povas
         redakti ĝin.
+      only_creator_or_revoker_can_edit: Nur la kontrolantoj, kiuj kreis aŭ nuligis
+        tiun ĉi blokadon povas redakti ĝin.
       success: Blokado ĝisdatigita.
     index:
       title: Blokadoj de uzanto
@@ -3158,14 +3169,15 @@ eo:
       custom_dimensions: Agordi proprajn dimensiojn
       format: 'Dosiertipo:'
       scale: 'Skalo:'
-      image_dimensions: Bildo montros la norman tavolon je distingivo %{width}×%{height}
+      image_dimensions: Bildo montros la tavolon “%{layer}” je distingivo %{width}×%{height}
       download: Elŝuti
       short_url: Mallonga retadreso
       include_marker: Inkludi markon
       center_marker: Centrigi mapon al marko
       paste_html: Engluu HTML-kodon al via retpaĝo
       view_larger_map: Vidi pli grandan mapon
-      only_standard_layer: Nur la norma tavolo de mapo elporteblas kiel bildon
+      only_standard_layer: Nur la tavoloj Norma, Biciklada kaj Transporta estas elporteblaj
+        kiel bildoj
     embed:
       report_problem: Raporti problemon
     key:
index 5d29738cf2c2ff4519cc94d0192ebbf02f143492..1d096a5d4f38936d11c12580d2d0b6bf21d4097a 100644 (file)
@@ -28,6 +28,7 @@
 # Author: Dgstranz
 # Author: Egofer
 # Author: Ejegg
+# Author: EmicraftNoob
 # Author: Eulalio
 # Author: Fitoschido
 # Author: Fortega
 es:
   time:
     formats:
-      friendly: '%e de %B de %Y a las %H:%M'
+      friendly: '%e %B %Y a las %H:%M'
   helpers:
     file:
       prompt: Seleccionar archivo
@@ -2809,6 +2810,7 @@ es:
       write_notes: Modifica notas
       write_redactions: Censurar datos del mapa
       read_email: Leer dirección de correo electrónico del usuario
+      send_messages: Enviar mensajes privados a otros usuarios
       skip_authorization: Auto aprobar aplicación
     for_roles:
       moderator: Este permiso es para acciones disponibles solo para moderadores.
@@ -3134,13 +3136,14 @@ es:
       show: Ver este bloqueo
       back: Ver todos los bloqueos
     filter:
-      block_expired: Este bloqueo ya ha expirado y no puede ser editado.
       block_period: El periodo de bloqueo debe de ser uno de los valores seleccionables
         de la lista desplegable.
     create:
       flash: Has creado un bloqueo en el usuario %{name}.
     update:
       only_creator_can_edit: Sólo el moderador que ha creado este bloqueo puede editarlo.
+      only_creator_or_revoker_can_edit: Solo los moderadores que han creado o revocado
+        este bloqueo pueden editarlo.
       success: Bloqueo actualizado.
     index:
       title: Bloqueos de usuario
@@ -3322,14 +3325,15 @@ es:
       custom_dimensions: Establecer dimensiones personalizadas
       format: 'Formato:'
       scale: 'Escala:'
-      image_dimensions: La imagen mostrará la capa estándar en %{width} x %{height}
+      image_dimensions: La imagen mostrará la capa %{layer} en %{width} x %{height}
       download: Descargar
       short_url: URL corta
       include_marker: Incluir marcador
       center_marker: Centrar mapa en el marcador
       paste_html: Pegar código HTML para incrustar en el sitio web
       view_larger_map: Ver el mapa más grande
-      only_standard_layer: Sólo la capa estándar se puede exportar como una imagen
+      only_standard_layer: Sólo las capas Estándar, Mapa Ciclista y Transporte pueden
+        exportarse como una imagen
     embed:
       report_problem: Reportar un problema
     key:
index 36bfb88ecfdd7a2205baa9ce7191d3393af30390..46660b44483f658381290c11cafcb22b1e8fa08e 100644 (file)
@@ -2853,7 +2853,6 @@ et:
       show: Vaata seda blokeeringut
       back: Vaata kõiki blokeeringuid
     filter:
-      block_expired: Blokeering on juba aegunud ja seda ei saa muuta.
       block_period: Blokeeringu ajavahemik peab olema üks valitav rippmenüü loendi
         väärtus.
     create:
index cbf41d0e0c9937765601aad2b4e31d05ba3bbef1..d8ca1f5b1af800595af53224e045ff74a47c67b3 100644 (file)
@@ -2800,7 +2800,6 @@ eu:
       show: Ikusi bloke hau
       back: Ikusi bloke guztiak
     filter:
-      block_expired: Blokea dagoeneko iraungi da eta ezin da editatu.
       block_period: Blokeoaren iraupena goitibeherako zerrendan hautatutako balioetariko
         bat izan behar da.
     create:
index cf92d804e5059386ec99a91f26ce95305377f092..bf6b5ec3fc371170af78d23e06fdcc3944eb37e1 100644 (file)
@@ -2544,7 +2544,6 @@ fa:
       show: دیدن این مسدودی
       back: دیدن تمام مسدودی‌ها
     filter:
-      block_expired: مسدودی قبلاً منقضی شده و قابل ویرایش نیست.
       block_period: دورهٔ مسدودی باید یکی از مقدارهای قابل انتخاب در لیست بازشو باشد.
     create:
       flash: یک مسدودی روی کاربری %{name} ایجاد شد.
index ee10ca3b7c6535466301f99a599a725abdc50dec..5e49f8ab8ddac5733236091d48de27f1ce4c86d6 100644 (file)
@@ -2731,7 +2731,6 @@ fi:
       show: Näytä tämä esto
       back: Näytä kaikki estot
     filter:
-      block_expired: Esto on jo vanhentunut, eikä sitä voi muokata.
       block_period: Eston ajanjakson täytyy olla yksi pudotusvalikossa olevista arvoista.
     create:
       flash: Estettiin käyttäjä %{name}
index 454b685ea4f0f76435d131493a222918c8403541..ab1c14f2bda47e2ca46c4ed56a01ed15d5ea3c31 100644 (file)
@@ -69,6 +69,7 @@
 # Author: Metroitendo
 # Author: Momo50WM
 # Author: Mulcyber
+# Author: Méthodes Bulebe Hangi
 # Author: Nemo bis
 # Author: Nicolapps
 # Author: Niridya
@@ -116,7 +117,7 @@ fr:
     dir: ltr
   time:
     formats:
-      friendly: '%e %B %Y à %H%M'
+      friendly: '%e %B %Y à %-H h %M'
       blog: '%e %B %Y'
   helpers:
     file:
@@ -138,8 +139,8 @@ fr:
         create: S’inscrire
         update: Mettre à jour
       redaction:
-        create: Créer la censure
-        update: Enregistrer la censure
+        create: Créer le masquage
+        update: Enregistrer le masquage
       trace:
         create: Téléverser
         update: Enregistrer les modifications
@@ -162,7 +163,7 @@ fr:
       changeset_tag: Attribut du groupe de modifications
       country: Pays
       diary_comment: Commentaire du journal
-      diary_entry: Entrée d’agenda
+      diary_entry: Entrée du journal
       friend: Ami(e)
       issue: Problème
       language: Langue
@@ -199,7 +200,7 @@ fr:
         support_url: URL de l’assistance
         allow_read_prefs: lire les préférences de l’utilisateur
         allow_write_prefs: modifier les préférences de l’utilisateur
-        allow_write_diary: créer des entrées de carnet, des commentaires et des liens
+        allow_write_diary: créer des entrées du journal, des commentaires et des liens
           d’amitié
         allow_write_api: modifier la carte
         allow_read_gpx: lire ses traces GPS privées
@@ -251,7 +252,7 @@ fr:
         email: Courriel
         new_email: Nouvelle adresse de courriel
         active: Actif
-        display_name: Afficher le nom
+        display_name: Pseudonyme
         description: Description du profil
         home_lat: Latitude
         home_lon: Longitude
@@ -347,7 +348,7 @@ fr:
         reopened_at_by_html: Réactivé à %{when} par %{user}
       rss:
         title: Notes OpenStreetMap
-        description_all: Une liste de notes rapportées, commentées ou fermées
+        description_all: Une liste de notes signalées, commentées ou fermées
         description_area: Une liste de notes, signalées, commentées ou fermées dans
           votre zone [(%{min_lat} ; %{min_lon}) – (%{max_lat} ; %{max_lon})]
         description_item: Un flux RSS pour la note %{id}
@@ -369,7 +370,7 @@ fr:
           utilisant le bouton ci-dessous. Veuillez prendre note des détails suivants :'
         delete_profile: Les informations de votre profil, y compris votre avatar,
           votre description et votre lieu de résidence seront supprimées.
-        delete_display_name: Votre nom affiché sera supprimé et pourra être réutilisé
+        delete_display_name: Votre pseudonyme sera supprimé et pourra être réutilisé
           pour d’autres comptes.
         retain_caveats: 'Cependant, quelques informations vous concernant seront conservées
           sur OpenStreetMap, même après la suppression de votre compte :'
@@ -396,12 +397,12 @@ fr:
       external auth: Authentification externe
       openid:
         link: https://wiki.openstreetmap.org/wiki/FR:OpenID
-        link text: qu’est-ce que cela ?
+        link text: qu’est-ce?
       public editing:
         heading: Modification publique
         enabled: Activée. Non anonyme et peut modifier les données.
         enabled link: https://wiki.openstreetmap.org/wiki/FR:Modifications_anonymes
-        enabled link text: qu’est-ce que ceci ?
+        enabled link text: qu’est-ce ?
         disabled: Désactivée et ne peut pas modifier les données ; toutes les précédentes
           modifications sont anonymes.
         disabled link text: pourquoi ne puis-je pas modifier ?
@@ -415,9 +416,9 @@ fr:
         agreed_with_pd: Vous avez également déclaré que vous considérez vos modifications
           comme relevant du domaine public.
         link: https://wiki.osmfoundation.org/wiki/Licence/Contributor_Terms/FR
-        link text: qu’est-ce que ceci ?
+        link text: qu’est-ce ?
       save changes button: Enregistrer les modifications
-      delete_account: Supprimer le compte...
+      delete_account: Supprimer le compte
     go_public:
       heading: Modification publique
       currently_not_public: Actuellement, vos modifications sont anonymes et les utilisateurs
@@ -458,10 +459,10 @@ fr:
       other: '%{count} chemins'
     download_xml: Télécharger en XML
     view_history: Voir l’historique
-    view_unredacted_history: Voir l'historique non censuré
+    view_unredacted_history: Voir l'historique non masqué
     view_details: Afficher les détails
-    view_redacted_data: Afficher les données censurées
-    view_redaction_message: Afficher le message de rédaction
+    view_redacted_data: Afficher les données masquées
+    view_redaction_message: Afficher le message de masquage
     location: 'Emplacement :'
     common_details:
       coordinates_html: '%{latitude} ; %{longitude}'
@@ -506,8 +507,8 @@ fr:
         note: note
     timeout:
       title: Erreur de dépassement du délai d’attente
-      sorry: Désolé, les données pour l’objet %{type} d’identifiant %{id} ont mis
-        trop de temps à être récupérées.
+      sorry: Désolé, obtenir les données pour l’objet %{type} d’identifiant %{id}
+        a pris trop de temps.
       type:
         node: nœud
         way: chemin
@@ -527,7 +528,7 @@ fr:
         navigateur lent ou le bloquer. Êtes-vous sûr de vouloir afficher ces données
         ?
       load_data: Charger les données
-      loading: Chargement en cours...
+      loading: Chargement en cours
     tag_details:
       tags: Attributs
       wiki_link:
@@ -546,18 +547,18 @@ fr:
       enclosing: Objets englobants
   old_nodes:
     not_found:
-      sorry: 'Désolé, le nœud #%{id} version %{version} est introuvable.'
+      sorry: Désolé, la version %{version} du nœud %{id} est introuvable.
   old_ways:
     not_found:
-      sorry: 'Désolé, la façon #%{id} version %{version} est introuvable.'
+      sorry: Désolé, la version %{version} du chemin %{id} est introuvable.
   old_relations:
     not_found:
-      sorry: 'Désolé, la relation #%{id} version %{version} est introuvable.'
+      sorry: Désolé, la version %{version} de la relation %{id} est introuvable.
   changesets:
     changeset_paging_nav:
       showing_page: Page %{page}
-      next: Suivant â\96¸
-      previous: â\97\82 Précédent
+      next: Suivant â\80º
+      previous: â\80¹Â Précédent
     changeset:
       anonymous: Anonyme
       no_edits: (aucune modification)
@@ -588,10 +589,10 @@ fr:
         closed: Fermé
         belongs_to: Auteur
     subscribe:
-      heading: S'abonner à la discussion sur l'ensemble de modifications suivante ?
-      button: S'abonner à la discussion
+      heading: S’abonner à la discussion sur l’ensemble de modifications suivant ?
+      button: Sabonner à la discussion
     unsubscribe:
-      heading: Se désabonner de la discussion du groupe de modifications suivant ?
+      heading: Se désabonner de la discussion du groupe de modifications suivant?
       button: Se désinscrire de la discussion
     heading:
       title: Groupe de modifications %{id}
@@ -599,9 +600,8 @@ fr:
     no_such_entry:
       title: Aucun ensemble de modifications de ce type
       heading: 'Aucune entrée avec l’identifiant : %{id}'
-      body: Désolé, il n’y a aucun groupe de modifications avec l'identifiant %{id}.
-        Veuillez vérifier l'orthographe ou la validité du lien sur lequel vous avez
-        cliqué.
+      body: Désolé, il n’y a aucun groupe de modifications avec l’identifiant %{id}.
+        Peut-être avez-vous fait une erreur en le recopiant ou suivi un lien erroné ?
     show:
       title: 'Groupe de modifications : %{id}'
       created: 'Créé : %{when}'
@@ -617,7 +617,7 @@ fr:
       subscribe: S’abonner
       unsubscribe: Se désabonner
       comment_by_html: Commentaire de %{user} %{time_ago}
-      hidden_comment_by_html: Commentaire caché de %{user} %{time_ago}
+      hidden_comment_by_html: Commentaire masqué de %{user} %{time_ago}
       hide_comment: masquer
       unhide_comment: démasquer
       comment: Commenter
@@ -631,22 +631,22 @@ fr:
       relations: Relations (%{count})
       relations_paginated: Relations (%{x} à %{y} sur %{count})
     timeout:
-      sorry: Désolé, la liste des groupes de modifications que vous avez demandée
-        a mis trop de temps à récupérer.
+      sorry: Désolé, récupérer la liste des groupes de modifications que vous avez
+        demandée a pris trop de temps.
   changeset_comments:
     comment:
       comment: Nouveau commentaire sur le groupe de modifications nº %{changeset_id}
         par %{author}
       commented_at_by_html: Mis à jour le %{when} par %{user}
     comments:
-      comment: Nouveau commentaire sur le groupe de modifications nº %{changeset_id}
+      comment: Nouveau commentaire sur le groupe de modifications %{changeset_id}
         par %{author}
     index:
       title_all: Discussion sur le groupe de modifications OpenStreetMap
-      title_particular: Discussion sur le groupe de modifications OpenStreetMap nº %{changeset_id}
+      title_particular: Discussion sur le groupe de modifications OpenStreetMap %{changeset_id}
     timeout:
-      sorry: Désolé, la liste des commentaires d’ensembles de modifications que vous
-        avez demandée est trop longue à récupérer.
+      sorry: Désolé, récupérer les commentaires du groupe de modifications que vous
+        avez demandés a pris trop de temps.
   dashboards:
     contact:
       km away: à %{count} km
@@ -660,7 +660,7 @@ fr:
       title: Mon tableau de bord
       no_home_location_html: '%{edit_profile_link} et définissez l’emplacement de
         votre domicile pour voir les utilisateurs à proximité.'
-      edit_your_profile: Modifier votre profil
+      edit_your_profile: Modifiez votre profil
       my friends: Mes amis
       no friends: Vous n’avez encore ajouté aucun ami.
       nearby users: Autres utilisateurs à proximité
@@ -680,12 +680,12 @@ fr:
       title: Journaux des utilisateurs
       title_friends: Journaux des amis
       title_nearby: Journaux des utilisateurs à proximité
-      user_title: Carnet de %{user}
-      in_language_title: Entrées du carnet en %{language}
+      user_title: Journal de %{user}
+      in_language_title: Entrées du journal en %{language}
       new: Nouvelle entrée du journal
       new_title: Écrire une nouvelle entrée dans mon journal utilisateur
       my_diary: Mon journal
-      no_entries: Aucune entrée de carnet
+      no_entries: Aucune entrée de journal
       recent_entries: Entrées récentes du journal
       older_entries: Entrées plus anciennes
       newer_entries: Entrées plus récentes
@@ -693,8 +693,8 @@ fr:
       title: Modifier l’entrée du journal
       marker_text: Emplacement de l’entrée du journal
     show:
-      title: Carnet de %{user} | %{title}
-      user_title: Carnet de %{user}
+      title: Journal de %{user} | %{title}
+      user_title: Journal de %{user}
       discussion: Discussion
       subscribe: S’abonner
       unsubscribe: Se désabonner
@@ -702,11 +702,11 @@ fr:
       login_to_leave_a_comment_html: '%{login_link} pour laisser un commentaire'
       login: Se connecter
     no_such_entry:
-      title: Aucune entrée de carnet correspondante
+      title: Aucune entrée de journal correspondante
       heading: 'Aucune entrée avec l’identifiant : %{id}'
-      body: Désolé, il n’y a aucune entrée ni commentaire de carnet avec l’identifiant
-        %{id}. Veuillez vérifier votre orthographe ou la validité du lien que vous
-        avez cliqué.
+      body: Désolé, il n’y a aucune entrée ni commentaire de journal avec l’identifiant
+        %{id}. Peut-être avez-vous fait une erreur en le recopiant ou suivi un lien
+        erroné ?
     diary_entry:
       posted_by_html: Publié par %{link_user} le %{created} en %{language_link}.
       updated_at_html: Dernière mise à jour le %{updated}.
@@ -738,8 +738,8 @@ fr:
         description: Entrées récentes du journal OpenStreetMap de %{user}
       language:
         title: Entrées du journal OpenStreetMap en %{language_name}
-        description: Entrées récentes des carnets d’utilisateurs d’OpenStreetMap en
-          %{language_name}
+        description: Entrées récentes des journaux d’utilisateurs d’OpenStreetMap
+          en %{language_name}
       all:
         title: Entrées des journaux OpenStreetMap
         description: Entrées récentes des journaux d’utilisateurs de OpenStreetMap
@@ -760,6 +760,8 @@ fr:
       comment: Commentaire
       newer_comments: Commentaires plus récents
       older_comments: Commentaires plus anciens
+    new:
+      heading: Ajouter un commentaire à cette discussion ?
   doorkeeper:
     errors:
       messages:
@@ -945,7 +947,7 @@ fr:
           prison: Prison
           pub: Pub
           public_bath: Bains publics
-          public_bookcase: Bibliothèque publique
+          public_bookcase: Microbibliothèque
           public_building: Bâtiment public
           ranger_station: Poste de garde forestière
           recycling: Point de recyclage
@@ -1755,6 +1757,7 @@ fr:
       maintenance essentielle à son bon fonctionnement est en cours.
     osm_read_only: La base de données OpenStreetMap est actuellement en mode lecture
       seule ; une maintenance essentielle à son bon fonctionnement est en cours.
+    nothing_to_preview: Rien à voir en avant.
     donate: Soutenez OpenStreetMap, %{link} au fonds de mise à niveau du matériel.
     help: Aide
     about: À propos
@@ -1805,13 +1808,19 @@ fr:
       befriend_them: 'Vous pouvez également l’ajouter comme ami(e) ici : %{befriendurl}.'
       befriend_them_html: Vous pouvez aussi l’ajouter comme ami à l’adresse %{befriendurl}.
     gpx_description:
+      description_with_tags: Il semble que votre fichier GPX « %{trace_name} » avec
+        la description « %{trace_description} » et les balises « %{tags} »
       description_with_tags_html: Il semble que votre fichier GPX « %{trace_name} »
         avec la description « %{trace_description} » et les balises « %{tags} »
+      description_with_no_tags: Il semble que votre fichier GPX « %{trace_name} »
+        avec la description « %{trace_description} » et sans balise
       description_with_no_tags_html: Il semble que votre fichier GPX « %{trace_name} »
         avec la description « %{trace_description} » et sans balise
     gpx_failure:
       hi: Bonjour %{to_user},
       failed_to_import: 'n’a pas pu être importé. Voici l’erreur :'
+      more_info: Vous trouverez plus d’informations sur les échecs d’import GPX et
+        comment les éviter à l’adresse %{url}.
       more_info_html: Vous trouverez plus d’informations sur les échecs d’import GPX
         et comment les éviter à l’adresse %{url}.
       import_failures_url: https://wiki.openstreetmap.org/wiki/GPX#Troubleshooting
@@ -1822,6 +1831,8 @@ fr:
         one: s’est chargé correctement avec %{trace_points} dd %{count} point possible.
         other: s’est chargé correctement avec %{trace_points} des %{count} points
           possibles.
+      all_your_traces: Toutes vos traces de GPX téléversées avec succès peuvent être
+        trouvées à %{url}.
       all_your_traces_html: Toutes vos traces de GPX téléversées avec succès peuvent
         être trouvées à %{url}.
       subject: '[OpenStreetMap] Import GPX réussi'
@@ -2671,6 +2682,7 @@ fr:
           Il n’est pas nécessaire d’établir formellement un groupe dans la même mesure que les chapitres locaux.
           En effet, de nombreux groupes existent avec beaucoup de succès en tant que rassemblement informel de personnes ou en tant que groupe communautaire. Chacun peut en créer ou en rejoindre un. En savoir plus sur la %{communities_wiki_link}.
         communities_wiki: page wiki des communautés
+        communities_wiki_url: https://wiki.openstreetmap.org/wiki/FR:User_group
   traces:
     visibility:
       private: Privé (partagé anonymement, points non ordonnés)
@@ -2806,6 +2818,7 @@ fr:
       oauth2_authorizations: Droits OAuth 2
       muted_users: Utilisateurs silencieux
     auth_providers:
+      openid_url: URL OpenID
       openid_login_button: Continuer
       openid:
         title: Connexion avec OpenID
@@ -2835,7 +2848,7 @@ fr:
       allow_to: 'Autoriser l’application cliente à :'
       allow_read_prefs: lire vos préférences utilisateur ;
       allow_write_prefs: modifier vos préférences utilisateur ;
-      allow_write_diary: créer des entrées dans votre carnet, faire des commentaires
+      allow_write_diary: créer des entrées dans votre journal, faire des commentaires
         et ajouter des ami(e)s ;
       allow_write_api: modifier la carte.
       allow_read_gpx: lire vos traces GPS privées ;
@@ -2867,6 +2880,8 @@ fr:
       write_notes: Modifier les notes
       write_redactions: Caviarder les données cartographiques
       read_email: Lire l’adresse courriel de l’utilisateur
+      consume_messages: Lire, modifier l’état et supprimer les messages de l’utilisateur
+      send_messages: Envoyer des messages privés à d’autres utilisateurs
       skip_authorization: Demande d’approbation automatique
     for_roles:
       moderator: Cette autorisation concerne les actions disponibles uniquement pour
@@ -3069,7 +3084,7 @@ fr:
       destroy_mute: Réactiver le son de cet utilisateur
       edit_profile: Modifier le profil
       send message: Envoyer un message
-      diary: Carnet
+      diary: Journal
       edits: Modifications
       traces: Traces
       notes: Notes de carte
@@ -3195,13 +3210,14 @@ fr:
       show: Afficher ce blocage
       back: Voir tous les blocages
     filter:
-      block_expired: Le blocage a déjà expiré et ne peut pas être modifié.
       block_period: La période de blocage doit être choisie dans la liste déroulante.
     create:
       flash: Blocage créé sur l’utilisateur « %{name} ».
     update:
       only_creator_can_edit: Seul le modérateur ou la modératrice qui a créé ce blocage
         peut le modifier.
+      only_creator_or_revoker_can_edit: Seuls les modérateurs ayant créé ou annulé
+        ce blocage peuvent le modifier.
       success: Blocage mis à jour.
     index:
       title: Blocages d’utilisateur
@@ -3392,7 +3408,8 @@ fr:
       center_marker: Centrer la carte sur le marqueur
       paste_html: Coller le HTML à inclure dans le site web
       view_larger_map: Afficher une carte plus grande
-      only_standard_layer: Seule la couche standard peut être exportée comme une image
+      only_standard_layer: Seule les couche « Standard », « Carte cyclable » et « Carte
+        de transport » peuvent être exportées comme une image
     embed:
       report_problem: Signaler un problème
     key:
index a8a7d20221136429c49fcf2bee72b93062b2913e..1618ea66be7a9d5c916639debf17051c5e9a9295 100644 (file)
@@ -2479,7 +2479,6 @@ fy:
       show: Dizze útsluting besjen
       back: Alle útslutings besjen
     filter:
-      block_expired: De útsluting is al ferrûn en kin net bewurke wurde.
       block_period: De útslutingsdoer moat ien fan 'e wearden yn 'e útklapbere karlist
         wêze.
     create:
index a60901e37e4a2f29c98a0409751fd2fa293c06f0..521eeb0a8a3dc781c0ff7c3558f02faf480b3e45 100644 (file)
@@ -1735,8 +1735,6 @@ gd:
       show: Seall am bacadh seo
       back: Seall a h-uile bacadh
     filter:
-      block_expired: Dh'fhalbh an ùine air a' bhacadh seo mar-thà is cha ghabh a dheasachadh
-        tuilleadh.
       block_period: Feumaidh eadaramh a' bhacaidh a bhith 'na aon dhe na luachan a
         ghabhas taghadh air an liosta-theàrnaidh.
     create:
index c68587eab28b9689a53cb44985952e3e764b50cc..49a80694e59c83d2c6637eef73cf1225948da11e 100644 (file)
@@ -418,10 +418,9 @@ gl:
         relation: relación
     start_rjs:
       feature_warning: Cargando %{num_features} funcións, que poden facer que o teu
-        navegador sexa lento ou non responda. Estás seguro de que queres mostrar estes
-        datos?
+        navegador sexa lento ou non responda. Queres mostrar estes datos?
       load_data: Cargar os datos
-      loading: Estase a carregar...
+      loading: Cargando...
     tag_details:
       tags: Etiquetas
       wiki_link:
@@ -655,7 +654,7 @@ gl:
       newer_comments: Comentarios máis recentes
       older_comments: Comentarios máis vellos
     new:
-      heading: Queres engadir un comentario á seguinte discusión sobre a entrada do
+      heading: Queres engadir un comentario á seguinte conversa sobre a entrada no
         diario?
   doorkeeper:
     errors:
@@ -865,7 +864,7 @@ gl:
           veterinary: Clínica veterinaria
           village_hall: Concello
           waste_basket: Cesto do lixo
-          waste_disposal: Contedor de lixo
+          waste_disposal: Colector do lixo
           waste_dump_site: Lugar de vertedoiro de lixo
           watering_place: Bebedoiro para animais
           water_point: Punto de auga
@@ -1645,6 +1644,7 @@ gl:
       traballos de mantemento nela.
     osm_read_only: A base de datos do OpenStreetMap atópase en modo de só lectura
       mentres realizamos traballos de mantemento nela.
+    nothing_to_preview: Non hai nada que previsualizar.
     donate: Apoie o OpenStreetMap %{link} ao fondo de actualización de hardware.
     help: Axuda
     about: Acerca de
@@ -1693,13 +1693,19 @@ gl:
       befriend_them: Tamén pode engadilo coma amizade no %{befriendurl}.
       befriend_them_html: Tamén podes engadilo como amizade no %{befriendurl}.
     gpx_description:
+      description_with_tags: 'Parece o teu ficheiro GPX %{trace_name} coa descrición
+        %{trace_description} e as seguintes etiquetas: %{tags}'
       description_with_tags_html: 'Parece o teu ficheiro GPX %{trace_name} coa descrición
         %{trace_description} e as seguintes etiquetas: %{tags}'
+      description_with_no_tags: Parece o teu ficheiro GPX %{trace_name} coa descrición
+        %{trace_description} e sen etiquetas
       description_with_no_tags_html: Parece o teu ficheiro GPX %{trace_name} coa descrición
         %{trace_description} e sen etiquetas
     gpx_failure:
       hi: 'Ola %{to_user}:'
       failed_to_import: 'erro ao importar. Velaquí atópase o erro:'
+      more_info: Máis información sobre os erros de importación de GPX e como evitalos
+        en %{url}.
       more_info_html: Máis información sobre os erros de importación de GPX e como
         evitalos en %{url}.
       subject: '[OpenStreetMap] Importación GPX errónea'
@@ -1710,6 +1716,8 @@ gl:
           posible.
         other: cargouse correctamente con %{trace_points} de entre %{count} puntos
           posibles.
+      trace_location: A túa pista está dispoñible en %{trace_url}
+      all_your_traces: Podes atopar todas as pistas GPX que subiches en %{url}
       all_your_traces_html: Podes atopar todas as pistas GPX que subiches en %{url}.
       subject: '[OpenStreetMap] Importación GPX correcta'
     signup_confirm:
@@ -2728,6 +2736,8 @@ gl:
       write_notes: Modificar notas
       write_redactions: Censurar datos do mapa
       read_email: Ver os enderezos de correo electrónico dos usuarios
+      consume_messages: Ver, actualizar o estado e borrar mensaxes dos usuarios
+      send_messages: Enviar mensaxes privadas aos usuarios
       skip_authorization: Aprobar automaticamente aplicacións
     for_roles:
       moderator: Estes permisos son para as accións dispoñibles unicamente para os
@@ -3047,13 +3057,14 @@ gl:
       show: Ollar este bloqueo
       back: Ollar tódolos bloqueos
     filter:
-      block_expired: O bloqueo xa caducou. Non se pode editar.
       block_period: O período de bloqueo debe elixirse de entre os valores presentes
         na listaxe despregábel.
     create:
       flash: Bloqueo creado para o usuario %{name}.
     update:
       only_creator_can_edit: Só o moderador que creou o bloqueo pode editalo.
+      only_creator_or_revoker_can_edit: Só os moderadores que crearon ou revogaron
+        o bloqueo poden editalo.
       success: Bloqueo actualizado.
     index:
       title: Bloqueos de usuario
@@ -3235,14 +3246,15 @@ gl:
       custom_dimensions: Estabelecer dimensións personalizadas
       format: 'Formato:'
       scale: 'Escala:'
-      image_dimensions: A imaxe amosará a capa estándar con %{width} x %{height}
+      image_dimensions: A imaxe amosará a capa %{layer} con %{width} x %{height}
       download: Baixar
       short_url: Enderezo URL curto
       include_marker: Incluí-lo marcador
       center_marker: Centrar o mapa no marcador
       paste_html: Pegue o código HTML para incluílo na páxina web
       view_larger_map: Ollar un mapa máis grande
-      only_standard_layer: Só a capa estándar pode exportarse coma unha imaxe
+      only_standard_layer: Só as capas estándar, ciclista e transporte poden exportarse
+        coma unha imaxe
     embed:
       report_problem: Denunciar un problema
     key:
@@ -3263,7 +3275,7 @@ gl:
           other: Estás a menos de %{count} pés deste punto
       base:
         standard: Estándar
-        cyclosm: CyclOSM (Ciclista)
+        cyclosm: CyclOSM
         cycle_map: Ciclista
         transport_map: Transporte
         tracestracktop_topo: Tracestrack Topo
index 66ae5f02c58232f91349e5c08be62fcd48199675..f42174086d432c6801fde8ffd0f9e219a3c7114f 100644 (file)
@@ -878,7 +878,7 @@ gu:
           third: ત્રીજું
           fourth: ચોથું
           fifth: પાંચમું
-          sixth: છઠ્ઠુ
+          sixth: છઠ્ઠુ
           seventh: સાતમું
           eighth: આઠમું
           ninth: નવમું
index c47aa81af10144c7b86f6b6d49be661d9c76a154..aeff2510981f18a903bacf061ddbdf3d5ca5b8e6 100644 (file)
@@ -1671,6 +1671,7 @@ he:
       המבוצעות בו.
     osm_read_only: מסד הנתונים של אתר OpenStreetMap נתון כעת במצב קריאה בלבד בשל עבודות
       תחזוקה המבוצעות בו.
+    nothing_to_preview: אין מה להראות בתצוגה מקדימה.
     donate: תִמכו ב־OpenStreetMap על־ידי %{link} לקרן לשדרוג החומרה.
     help: עזרה
     about: אודות
@@ -1714,14 +1715,20 @@ he:
       befriend_them: באפשרותך לסמנו כחבר בכתובת %{befriendurl}.
       befriend_them_html: באפשרותך לסמנו כחבר בכתובת %{befriendurl}.
     gpx_description:
-      description_with_tags_html: 'נראה כי קובץ ה־GPX שלך %{trace_name} העונה לתיאור
-        %{trace_description} והתגיות הבאות: %{tags}'
-      description_with_no_tags_html: נראה כי קובץ ה־GPX שלך %{trace_name} העונה לתיאור
-        %{trace_description} וללא תגיות
+      description_with_tags: 'זה נראה כמו קובץ ה־GPX שלך %{trace_name} עם התיאור %{trace_description}
+        ועם התגים הבאים: %{tags}'
+      description_with_tags_html: 'זה נראה כמו קובץ ה־GPX שלך %{trace_name} עם התיאור
+        %{trace_description} ועם התגים הבאים: %{tags}'
+      description_with_no_tags: זה נראה כמו קובץ ה־GPX שלך %{trace_name} עם התיאור
+        %{trace_description} וללא תגים
+      description_with_no_tags_html: זה נראה כמו קובץ ה־GPX שלך %{trace_name} עם התיאור
+        %{trace_description} וללא תגים
     gpx_failure:
       hi: שלום %{to_user},
       failed_to_import: 'לא יובא כראוי. הינה השגיאה:'
-      more_info_html: מידע על תקלות בייבוא GPX וכיצד להימנע מהן נמצא תחת %{url}.
+      more_info: מידע נוסף על תקלות ביבוא GPX ועל איך להימנע מהן נמצא בכתובת %{url}.
+      more_info_html: מידע נוסף על תקלות ביבוא GPX ועל איך להימנע מהן נמצא בכתובת
+        %{url}.
       subject: '[אופן סטריט מאפ OpenStreetMap] שגיאה בייבוא GPX'
     gpx_success:
       hi: שלום %{to_user},
@@ -1730,6 +1737,8 @@ he:
         two: נטען בהצלחה עם %{trace_points} נקודות מתוך %{count} נקודות אפשריות.
         many: נטען בהצלחה עם %{trace_points} נקודות מתוך %{count} נקודות אפשריות.
         other: נטען בהצלחה עם %{trace_points} נקודות מתוך %{count} נקודות אפשריות.
+      trace_location: ההקלטה שלך זמינה בכתובת %{trace_url}
+      all_your_traces: אפשר למצוא את כל הקלטות ה־GPX שלך בכתובת %{url}
       all_your_traces_html: אפשר למצוא את כל עקבות ה־GPX שלך שהועלו בהצלחה דרך %{url}.
       subject: '[אופן סטריט מאפ OpenStreetMap] ייבוא GPX הצליח'
     signup_confirm:
@@ -2699,6 +2708,8 @@ he:
       write_notes: לשנות הערות
       write_redactions: שינוי נתוני המפה
       read_email: לקרוא את כתובת הדוא"ל של המשתמש
+      consume_messages: קריאה, עדכון מצב ומחיקה של הודעות משתמשים
+      send_messages: שליחת הודעה פרטית למשתמשים אחרים
       skip_authorization: לאשר את היישום אוטומטית
     for_roles:
       moderator: ההרשאה הזאת מיועדת לפעולות שזמינות רק למפקחים
@@ -3003,12 +3014,13 @@ he:
       show: הצגת החסימה הזאת
       back: הצגת כל החסימות
     filter:
-      block_expired: החסימה כבר פקעה ואי־אפשר לערוך אותה.
       block_period: תקופת החסימה צריכה להיות אחד הערכים שאפשר לבחור ברשימה הנפתחת.
     create:
       flash: נוצרה חסימה על חשבון %{name}
     update:
       only_creator_can_edit: רק המפקח שיצר את החסימה הזאת יכול לערוך אותה.
+      only_creator_or_revoker_can_edit: רק המפקחים שיצרו או ביטלו את החסימה הזאת יכולים
+        לערוך אותה.
       success: החסימה עודכנה.
     index:
       title: חסימות משתמש
index ef76c43a865dc2219db5562474ab12a4e38d3e61..e2f4ef99d0aeb22e75382b4a2582f74e9f3ebd5f 100644 (file)
@@ -1737,7 +1737,6 @@ hr:
       show: Prikaži ovu blokadu
       back: Prikaži sve blokade
     filter:
-      block_expired: Blokada je već istekla i ne može se uređivati.
       block_period: Period blokade mora biti jedna od vrijednosti iz padajuće liste.
     create:
       flash: Napravi blokadu na korisnika  %{name}.
index 9977b0942b4d71d8f1caf69f22e9220568212780..78b9281f0de3fcefe817753a0b00528ba6eef22e 100644 (file)
@@ -2573,7 +2573,6 @@ hsb:
       show: Tute blokowanje pokazać
       back: Wšě blokowanja pokazać
     filter:
-      block_expired: Blokowanje je hižo spadnjene a njeda so wobdźěłać.
       block_period: Doba blokowanja dyrbi jedna z hódnotow być, kotrež hodźa so z
         padaceho menija wubrać.
     create:
index 487a061aec6517c75a2d6ada1a23eed1cc6bbb62..16273c5f0bab764784c63a46848655c634f2b9a4 100644 (file)
@@ -2916,7 +2916,6 @@ hu:
       show: blokkolás megjelenítése
       back: Összes blokkolás megjelenítése
     filter:
-      block_expired: A blokkolás már lejárt, és nem szerkeszthető.
       block_period: A blokkolási időszaknak egy, a legördülő listából kiválasztható
         értéknek kell lennie.
     create:
index 2599f2a548949350cde8decb88f89686374cd69c..cb72dcccbbb204f96d81c9af08fe97fc57bc8b5a 100644 (file)
@@ -4,6 +4,7 @@
 # Author: Carlosedepaula
 # Author: Fanjiayi
 # Author: Julian Mendez
+# Author: Karmwiki
 # Author: Macofe
 # Author: McDutchie
 # Author: Nemo bis
@@ -2689,6 +2690,7 @@ ia:
       write_notes: Modificar notas
       write_redactions: Censurar datos del carta
       read_email: Leger le adresse de e-mail del usator
+      send_messages: Inviar messages private a altere usatores
       skip_authorization: Approbar automaticamente le application
     for_roles:
       moderator: Iste permission es pro actiones que es disponibile solmente al moderatores
@@ -3004,7 +3006,6 @@ ia:
       show: Examinar iste blocada
       back: Examinar tote le blocadas
     filter:
-      block_expired: Le blocada ha ja expirate e non pote esser modificate.
       block_period: Le periodo de blocada debe esser un del valores seligibile in
         le lista disrolante.
     create:
index b69f47e04b5589d8ccb4c044b09fc02699e39b91..5b2636b83d58e49cc0b9f6b33035bdd4be40af2d 100644 (file)
@@ -1640,13 +1640,19 @@ id:
       befriend_them: Anda juga dapat menambahkannua sebagai teman di %{befriendurl}.
       befriend_them_html: Anda juga bisa menambahkan mereka sebagai teman di %{befriendurl}.
     gpx_description:
+      description_with_tags: 'Kelihatannya berkas GPX Anda %{trace_name} dengan deskripsi
+        %{trace_description} dan tag-tag berikut: %{tags}'
       description_with_tags_html: 'Kelihatannya berkas GPX Anda %{trace_name} dengan
         deskripsi %{trace_description} dan tag-tag berikut: %{tags}'
+      description_with_no_tags: Kelihatannya berkas GPX Anda %{trace_name} dengan
+        deskripsi %{trace_description} dan tanpa tag
       description_with_no_tags_html: Kelihatannya berkas GPX Anda %{trace_name} dengan
         deskripsi %{trace_description} dan tanpa tag
     gpx_failure:
       hi: Halo %{to_user},
       failed_to_import: 'gagal melakukan impor. Berikut ini adalah kesalahannya:'
+      more_info: Informasi lebih lanjut tentang kegagalan impor GPX dan cara menghindarinya
+        bisa ditemukan di %{url}.
       more_info_html: Informasi lebih lanjut tentang kegagalan impor GPX dan cara
         menghindarinya bisa ditemukan di %{url}.
       subject: '[OpenStreetMap] gagal impor GPX'
@@ -1654,6 +1660,9 @@ id:
       hi: Halo %{to_user},
       loaded:
         other: berhasil dimuat dengan %{trace_points} dari %{count} titik yang mungkin.
+      trace_location: Trace Anda tersedia di %{trace_url}
+      all_your_traces: Semua jejak GPX Anda yang berhasil diunggah dapat ditemukan
+        di %{url}.
       all_your_traces_html: Semua jejak GPX Anda yang berhasil diunggah dapat ditemukan
         di %{url}.
       subject: '[OpenStreetMap] impor GPX sukses'
@@ -2634,6 +2643,8 @@ id:
       write_notes: Ubah catatan
       write_redactions: Sunting data peta
       read_email: Baca alamat surel pengguna
+      consume_messages: Baca, update status dan hapus pesan pengguna
+      send_messages: Kirim pesan pribadi ke pengguna ini
       skip_authorization: Setujui aplikasi secara otomatis
   oauth_clients:
     new:
@@ -2925,7 +2936,6 @@ id:
       show: Lihat blokir ini
       back: Lihat semua blokir
     filter:
-      block_expired: Blokir sudah kadaluwarsa dan tidak bisa diedit.
       block_period: Periode blokir harus merupakan salah satu nilai yang dapat dipilih
         dari daftar drop-down atau pilihan.
     create:
index 4a899c9e3c0f7bf5ffd504f601e1fb03cb63547f..897f9237ab30ae37a7aa9dabf594af2bb30ecb41 100644 (file)
@@ -20,6 +20,8 @@ is:
     formats:
       friendly: '%e. %B %Y kl. %H:%M'
       blog: '%e. %B %Y'
+  count:
+    at_least_pattern: '%{count}+'
   helpers:
     file:
       prompt: Veldu skrá
@@ -53,6 +55,11 @@ is:
       messages:
         invalid_email_address: lítur ekki út fyrir að vera gilt tölvupóstfang
         email_address_not_routable: er ekki nothæft
+        display_name_is_user_n: getur ekki verið user_n nema n sé notandaauðkennið
+          þitt
+      models:
+        user_mute:
+          is_already_muted: er nú þegar þaggað
     models:
       acl: Aðgangslisti
       changeset: Breytingasett
@@ -84,7 +91,7 @@ is:
       tracetag: Merki ferils
       user: Notandi
       user_preference: Notandastillingar
-      user_token: Leynistrengur notanda
+      user_token: Aðgangsteikn notanda
       way: Leið
       way_node: Leiðarliður
       way_tag: Merki leiðar
@@ -214,6 +221,7 @@ is:
         other: fyrir %{count} árum síðan
   printable_name:
     with_name_html: '%{name} (%{id})'
+    current_and_old_links_html: '%{current_link}, %{old_link}'
   editor:
     default: Sjálfgefið (núna %{name})
     id:
@@ -225,8 +233,10 @@ is:
   auth:
     providers:
       none: Ekkert
+      openid: OpenID
       google: Google
       facebook: Facebook
+      microsoft: Microsoft
       github: GitHub
       wikipedia: Wikipedia
   api:
@@ -242,6 +252,8 @@ is:
         reopened_at_by_html: Endurvirkjað %{when} af %{user}
       rss:
         title: Minnispunktar OpenStreetMap
+        description_all: Listi yfir minnispunkta sem hafa verið tilkynntir, gerðar
+          athugasemdir við eða hefur verið lokað
         description_area: Listi yfir minnispunkta sem hafa verið tilkynntir, gerðar
           athugasemdir við eða hefur verið lokað á svæðinu þínu [(%{min_lat}|%{min_lon})
           -- (%{max_lat}|%{max_lon})]
@@ -277,6 +289,8 @@ is:
         retain_changeset_discussions: Umræður þínar um breytingar, ef einhverjar eru,
           verða geymdar.
         retain_email: Netfangið þitt verður geymt.
+        recent_editing_html: Þar sem þú hefur nýverið gert breytingar er ekki hægt
+          að eyða aðgangnum þínum. Eyðing verður möguleg eftir %{time}.
         confirm_delete: Ertu viss?
         cancel: Hætta við
   accounts:
@@ -291,6 +305,7 @@ is:
       public editing:
         heading: Nafngreindar breytingar
         enabled: Virkt. Ekki nafnlaus og getur breytt gögnum.
+        enabled link: https://wiki.openstreetmap.org/wiki/Anonymous_edits
         enabled link text: Hvað er þetta?
         disabled: Óvirkur og getur ekki breytt gögnum, allar fyrri breytingar eru
           ónafngreindar.
@@ -304,6 +319,7 @@ is:
           skilmálana vegna framlags þíns.
         agreed_with_pd: Þú hefur einnig lýst því yfir að breytingar þínar verði í
           almenningseigu (Public Domain).
+        link: https://wiki.osmfoundation.org/wiki/Licence/Contributor_Terms
         link text: Hvað er þetta?
       save changes button: Vista breytingar
       delete_account: Eyði aðgangi...
@@ -332,6 +348,7 @@ is:
     deleted_ago_by_html: Eytt %{time_ago} af %{user}
     edited_ago_by_html: Breytt %{time_ago} af %{user}
     version: Útgáfa
+    redacted_version: Endurskoðuð útgáfa
     in_changeset: Breytingasett
     anonymous: nafnlaus
     no_comment: (engin athugasemd)
@@ -344,7 +361,10 @@ is:
       other: '%{count} leiðir'
     download_xml: Sækja XML
     view_history: Skoða feril
+    view_unredacted_history: Sjá óendurskoðaða útgáfu
     view_details: Skoða nánar
+    view_redacted_data: Sjá endurskoðuð gögn
+    view_redaction_message: Sjá skilaboð með yfirferð
     location: 'Staðsetning:'
     common_details:
       coordinates_html: '%{latitude}, %{longitude}'
@@ -427,6 +447,15 @@ is:
       introduction: Smelltu á kortið til að finna fitjur í nágrenninu.
       nearby: Nálægar fitjur
       enclosing: Umlykjandi fitjur
+  old_nodes:
+    not_found:
+      sorry: 'Því miður, liðurinn #%{id} útgáfa %{version} fannst ekki.'
+  old_ways:
+    not_found:
+      sorry: 'Því miður, leiðin #%{id} útgáfa %{version} fannst ekki.'
+  old_relations:
+    not_found:
+      sorry: 'Því miður, venslin #%{id} útgáfa %{version} fundust ekki.'
   changesets:
     changeset_paging_nav:
       showing_page: Síða %{page}
@@ -461,8 +490,24 @@ is:
         created: Búið til
         closed: Lokað
         belongs_to: Höfundur
+    subscribe:
+      heading: Gerast áskrifandi að umræðu með breytingasetti?
+      button: Gerast áskrifandi að umræðu
+    unsubscribe:
+      heading: Hætta áskrift að umræðu með breytingasetti?
+      button: Hætta áskrift að umræðu
+    heading:
+      title: Breytingasett %{id}
+      created_by_html: Útbúið af %{link_user} þann %{created}.
+    no_such_entry:
+      title: Ekkert slíkt breytingasett
+      heading: 'Engin færsla er til með auðkennið: %{id}'
+      body: Breytingasett númerið %{id} er ekki til. Kannski settirðu inn rangt stafsetta
+        slóð eða fylgdir ógildum tengli.
     show:
       title: 'Breytingasett: %{id}'
+      created: 'Búið til: %{when}'
+      closed: 'Lokað: %{when}'
       created_ago_html: Búið til %{time_ago}
       closed_ago_html: Lokað %{time_ago}
       created_ago_by_html: Búið til %{time_ago} af %{user}
@@ -550,6 +595,9 @@ is:
     show:
       title: Blogg %{user} | %{title}
       user_title: Blogg %{user}
+      discussion: Umræða
+      subscribe: Gerast áskrifandi
+      unsubscribe: Hætta í áskrift
       leave_a_comment: Bæta við athugasemd
       login_to_leave_a_comment_html: '%{login_link} til að bæta við athugasemd'
       login: Skrá inn
@@ -593,6 +641,12 @@ is:
       all:
         title: OpenStreetMap bloggfærslur
         description: Nýjustu bloggfærslur frá notendum OpenStreetMap
+    subscribe:
+      heading: Gerast áskrifandi að umræðu með bloggfærslu?
+      button: Gerast áskrifandi að umræðu
+    unsubscribe:
+      heading: Hætta áskrift að umræðu með bloggfærslu?
+      button: Hætta áskrift að umræðu
   diary_comments:
     index:
       title: Dagbók Athugasemdir bætt við af %{user}
@@ -604,11 +658,40 @@ is:
       comment: Athugasemd
       newer_comments: Nýrri athugasemdir
       older_comments: Eldri athugasemdir
+    new:
+      heading: Bæta athugasemd við umræðu með bloggfærslu?
   doorkeeper:
+    errors:
+      messages:
+        account_selection_required: Auðkenningarþjónninn krefst þess að reikningur
+          endanotanda sé valinn
+        consent_required: Auðkenningarþjónninn krefst samþykkis endanotanda
+        interaction_required: Auðkenningarþjónninn krefst aðgerðar af hálfu endanotanda
+        login_required: Auðkenningarþjónninn krefst auðkenningar endanotanda
     flash:
       applications:
         create:
           notice: Umsókn skráð.
+    openid_connect:
+      errors:
+        messages:
+          auth_time_from_resource_owner_not_configured: Brást vegna þess að uppsetningu
+            Doorkeeper::OpenidConnect.configure.auth_time_from_resource_owner vantar.
+          reauthenticate_resource_owner_not_configured: Brást vegna þess að uppsetningu
+            Doorkeeper::OpenidConnect.configure.reauthenticate_resource_owner vantar.
+          resource_owner_from_access_token_not_configured: Brást vegna þess að uppsetningu
+            Doorkeeper::OpenidConnect.configure.resource_owner_from_access_token vantar.
+          select_account_for_resource_owner_not_configured: Brást vegna þess að uppsetningu
+            Doorkeeper::OpenidConnect.configure.select_account_for_resource_owner
+            vantar.
+          subject_not_configured: Gerð auðkennisteikns brást vegna þess að uppsetningu
+            Doorkeeper::OpenidConnect.configure.subject vantar.
+    scopes:
+      address: Skoðaðu heimilisfangið þitt
+      email: Skoðaðu tölvupóstfangið þitt
+      openid: Auðkenndu notandaaðganginn þinn
+      phone: Skoðaðu símanúmerið þitt
+      profile: Skoðaðu persónuupplýsingar þínar
   errors:
     contact:
       contact_url: https://wiki.openstreetmap.org/wiki/Contact
@@ -617,6 +700,10 @@ is:
       contact_the_community_html: Ekki hika við að %{contact_link} OpenStreetMap-samfélagið
         ef þú hefur fundið bilaðan tengil eða villu. Taktu niður nákvæma vefslóð beiðni
         þinnar.
+    bad_request:
+      title: Ógild beiðni
+      description: Aðgerðin sem þú baðst um á OpenStreetMap-þjóninum er ekki gild
+        (HTTP 400)
     forbidden:
       title: Bannað
       description: Aðgerðin sem þú baðst um á OpenStreetMap-þjóninum er aðeins í boði
@@ -814,6 +901,7 @@ is:
           college: Framhaldsskólabygging
           commercial: Verslunarhús
           construction: Bygging á framkvæmdastigi
+          cowshed: Fjós
           detached: Aðskilið hús
           dormitory: Heimavist
           duplex: Parhús
@@ -843,6 +931,7 @@ is:
           shed: Skúr
           stable: Hesthús
           static_caravan: Hjólhýsi
+          sty: Stía
           temple: Trúarleg bygging
           terrace: Raðhús
           train_station: Lestarstöðvarbygging
@@ -1495,7 +1584,7 @@ is:
       title_html: Tilkynna %{link}
       missing_params: Get ekki búið til nýja skýrslu
       disclaimer:
-        intro: 'Áður en þú sendir skýrsluna þína inn til stjórnenda vefsins, skaltu
+        intro: 'Áður en þú sendir skýrsluna þína inn til umsjónarmanna vefsins, skaltu
           ganga úr skugga um að:'
         not_just_mistake: Þú sért viss um að vandamálið sé ekki bara mistök
         unable_to_fix: Þér hefur sjálfum ekki tekist að leysa vandamálið eða með hjálp
@@ -1554,7 +1643,10 @@ is:
     intro_text: OpenStreetMap er heimskort gert af fólki eins og þér. Það er gefið
       út með opnu hugbúnaðarleyfi og það kostar ekkert að nota það.
     intro_2_create_account: Búa til notandaaðgang
+    hosting_partners_2024_html: Vefhýsing er studd af %{fastly}, %{corpmembers} og
+      öðrum %{partners}.
     partners_fastly: Fastly
+    partners_corpmembers: Fyrirtækjameðlimir OSMF
     partners_partners: samstarfsaðilum
     tou: Notkunarskilmálar
     osm_offline: OpenStreetMap gagnagrunnurinn er niðri vegna viðhalds.
@@ -1575,6 +1667,7 @@ is:
     more: Meira
   user_mailer:
     diary_comment_notification:
+      description: 'OpenStreetMap bloggfærsla #%{id}'
       subject: '[OpenStreetMap] %{user} bætti athugasemd við bloggfærslu þína'
       hi: Hæ %{to_user},
       header: '%{from_user} hefur bætt við athugasemd á OpenStreetMap bloggfærsluna
@@ -1585,6 +1678,8 @@ is:
         á %{commenturl} eða sent skilaboð til höfundarins á %{replyurl}
       footer_html: Þú getur einnig lesið athugasemdina á %{readurl} og skrifað athugasemd
         á %{commenturl} eða sent skilaboð til höfundarins á %{replyurl}
+      footer_unsubscribe: Þú getur hætt áskrift að umræðunni á %{unsubscribeurl}
+      footer_unsubscribe_html: Þú getur hætt áskrift að umræðunni á %{unsubscribeurl}
     message_notification:
       subject: '[OpenStreetMap] %{message_title}'
       hi: Hæ %{to_user},
@@ -1605,13 +1700,19 @@ is:
       befriend_them: Þú getur líka bætt þeim við sem vinum á %{befriendurl}.
       befriend_them_html: Þú getur líka bætt þeim við sem vinum á %{befriendurl}.
     gpx_description:
+      description_with_tags: 'Hitt sér út sem að þinn GPX-fil %{trace_name} með lýsingunni
+        %{trace_description} og eftirfarandi merki: %{tags}'
       description_with_tags_html: 'Hitt sér út sem að þinn GPX-fil %{trace_name} með
         lýsingunni %{trace_description} og eftirfarandi merki: %{tags}'
+      description_with_no_tags: Hitt sér út sem að þinn GPX-fil %{trace_name} með
+        lýsingunni %{trace_description} og engin merki
       description_with_no_tags_html: Hitt sér út sem að þinn GPX-fil %{trace_name}
         með lýsingunni %{trace_description} og engin merki
     gpx_failure:
       hi: Hæ %{to_user},
       failed_to_import: 'tókst ekki að flytja inn. Hér er villan:'
+      more_info: Frekari upplýsingar um bilanir í GPX-innflutningi og hvernig á að
+        forðast þær má finna á %{url}.
       more_info_html: Frekari upplýsingar um bilanir í GPX-innflutningi og hvernig
         á að forðast þær má finna á %{url}.
       import_failures_url: https://wiki.openstreetmap.org/wiki/GPX_Import_Failures
@@ -1621,6 +1722,9 @@ is:
       loaded:
         one: var hlaðið inn með %{trace_points} af %{count} punkti mögulegum.
         other: var hlaðið inn með %{trace_points} punktum af %{count} mögulegum.
+      trace_location: Ferillinn þinn er núna tiltækur á %{trace_url}
+      all_your_traces: Alla GPX-ferla sem þú hefur sent inn má finna á %{url}
+      all_your_traces_html: Alla GPX-ferla sem þú hefur sent inn má finna á %{url}.
       subject: '[OpenStreetMap] GPX skrá flutt inn'
     signup_confirm:
       subject: '[OpenStreetMap] Velkomin í OpenStreetMap'
@@ -1646,6 +1750,7 @@ is:
       click_the_link: Ef þú óskaðir eftir þessari endurstillingu, skaltu fylgja tenglinum
         hér fyrir neðan til að staðfesta breytinguna.
     note_comment_notification:
+      description: 'OpenStreetMap-minnispunktur #%{id}'
       anonymous: Nafnlaus notandi
       greeting: Hæ,
       commented:
@@ -1687,9 +1792,10 @@ is:
           hefur gert athugasemd við. Minnispunkturinn er nálægt %{place}.'
         commented_note_html: '%{commenter} hefur endurvirkjað minnispunkt á korti
           sem þú hefur gert athugasemd við. Minnispunkturinn er nálægt %{place}.'
-      details: Nánari upplýsingar um minnispunktinn er að finna á %{url}.
-      details_html: Nánari upplýsingar um minnispunktinn er að finna á %{url}.
+      details: Svaraðu eða fáðu nánari upplýsingar um minnispunktinn á %{url}.
+      details_html: Svaraðu eða fáðu nánari upplýsingar um minnispunktinn á %{url}.
     changeset_comment_notification:
+      description: 'OpenStreetMap-breytingasett #%{id}'
       hi: Hæ %{to_user},
       greeting: Hæ,
       commented:
@@ -1708,12 +1814,11 @@ is:
         partial_changeset_with_comment: með umsögninni '%{changeset_comment}'
         partial_changeset_with_comment_html: með umsögninni '%{changeset_comment}'
         partial_changeset_without_comment: án athugasemdar
-      details: Nánari upplýsingar um breytingasettið er að finna á %{url}.
-      details_html: Nánari upplýsingar um breytingasettið er að finna á %{url}.
-      unsubscribe: Til að hætta áskrift að uppfærslum á þessu breytingasetti, farðu
-        þá á %{url} og smelltu á "Segja upp áskrift".
-      unsubscribe_html: Til að hætta áskrift að uppfærslum á þessu breytingasetti,
-        farðu þá á %{url} og smelltu á "Segja upp áskrift".
+      details: Svaraðu eða fáðu nánari upplýsingar um breytingasettið á %{url}.
+      details_html: Svaraðu eða fáðu nánari upplýsingar um breytingasettið á %{url}.
+      unsubscribe: Þú getur hætt áskrift að uppfærslum á þessu breytingasetti á %{url}.
+      unsubscribe_html: Þú getur hætt áskrift að uppfærslum á þessu breytingasetti
+        á %{url}.
   confirmations:
     confirm:
       heading: Skoðaðu tölvupóstinn þinn!
@@ -1736,7 +1841,7 @@ is:
       press confirm button: Hér getur þú staðfest breytingu á netfangi.
       button: Staðfesta
       success: Breyting á netfanginu þínu hefur verið staðfest.
-      failure: Netfang hefur þegar verið staðfest með þessum lykli.
+      failure: Netfang hefur þegar verið staðfest með þessu aðgangsteikni.
       unknown_token: Þessi staðfestingarkóði er útrunninn eða er ekki til staðar.
     resend_success_flash:
       confirmation_sent: Við höfum sent nýja staðfestingarmiða til %{email} og um
@@ -1792,6 +1897,9 @@ is:
       people_mapping_nearby: nálæga notendur
     muted:
       title: Þögguð skilaboð
+      messages:
+        one: '%{count} þögguð skilaboð'
+        other: Þú ert með %{count} þögguð skilaboð
     reply:
       wrong_user: Þú hefur skráð þig inn sem `%{user}' en skilaboðin sem þú baðst
         um að svara voru ekki send til þess notanda. Skráðu þig inn sem réttan notanda
@@ -1810,9 +1918,13 @@ is:
     heading:
       my_inbox: Innhólfið mitt
       my_outbox: Úthólfið mitt
+      muted_messages: Þögguð skilaboð
     mark:
       as_read: Skilaboðin voru merkt sem lesin
       as_unread: Skilaboðin voru merkt sem ólesin
+    unmute:
+      notice: Skilaboð voru færð í Innhólf
+      error: Ekki var hægt að færa skilaboðin í innhólfið.
     destroy:
       destroyed: Skilaboðunum var eytt
   passwords:
@@ -1823,13 +1935,18 @@ is:
       new password button: Endurstilla lykilorð
       help_text: Sláðu inn netfangið sem þú skráðir þig með, við munum senda tengil
         á það sem þú getur notað til að breyta lykilorðinu þínu.
+    create:
+      send_paranoid_instructions: Ef tölvupóstfangið þitt fyrirfinnst í gagnagrunninum
+        okkar, munt þú innan nokkurra mínútna fá tölvupóst með tengli til að endurheimta
+        lykilorðið þitt.
     edit:
       title: Endurstilla lykilorð
       heading: Endurstilla lykilorð fyrir %{user}
       reset: Endurstilla lykilorð
-      flash token bad: Þessi leynistrengur fannst ekki, kannski er slóðin röng?
+      flash token bad: Þetta aðgangsteikn fannst ekki, kannski er slóðin röng?
     update:
       flash changed: Lykilorðinu þínu hefur verið breytt
+      flash token bad: Þetta aðgangsteikn fannst ekki, kannski er slóðin röng?
   preferences:
     show:
       title: Kjörstillingar
@@ -1852,6 +1969,7 @@ is:
       image: Mynd
       gravatar:
         gravatar: Nota Gravatar-auðkennismynd
+        link: https://wiki.openstreetmap.org/wiki/Gravatar
         what_is_gravatar: Hvað er Gravatar?
         disabled: Gravatar-auðkennismynd hefur verið gerð óvirk.
         enabled: Birting Gravatar-auðkennismyndar hefur verið gerð virk.
@@ -1871,15 +1989,17 @@ is:
       failure: Gat ekki uppfært kjörstillingar.
   sessions:
     new:
-      title: Innskrá
-      tab_title: Innskrá
+      title: Skrá inn
+      tab_title: Skrá inn
+      login_to_authorize_html: Skráðu inn á OpenStreetMap til að fá aðgang að %{client_app_name}.
       email or username: Tölvupóstur eða notandanafn
       password: Lykilorð
       remember: Muna innskráninguna
       lost password link: Gleymdirðu lykilorðinu þínu?
-      login_button: Innskrá
+      login_button: Skrá inn
       register now: Skrá þig núna
-      with external: 'Þú getur líka notað utanaðkomandi þjónustur til innskráningar:'
+      with external: eða skráð inn með utanaðkomandi þjónustu
+      or: eða
       auth failure: Þetta notandanafn eða lykilorð er rangt.
     destroy:
       title: Útskráning
@@ -1907,6 +2027,7 @@ is:
       image: Mynd
       alt: Alt-texti
       url: Vefslóð
+      codeblock: Kóðablokk
     richtext_field:
       edit: Breyta
       preview: Forskoða
@@ -2069,7 +2190,13 @@ is:
           Resources Canada), og StatCan (Geography Division,
           Statistics Canada).
         contributors_ca_canada: Kanada
+        contributors_cz_credit_html: |-
+          %{czechia}: Inniheldur gögn frá Ríkisumsýslu landmælinga
+          og Landskrá fasteigna gefið út með %{cc_licence_link} notkunarleyfi
         contributors_cz_czechia: Tékkland
+        contributors_cz_cc_licence: Creative Commons HöfundarGetið 4.0 alþjóðlegt
+          notkunarleyfi (CC BY 4.0)
+        contributors_cz_cc_licence_url: https://creativecommons.org/licenses/by/4.0/
         contributors_fi_credit_html: |-
           %{finland}: Inniheldur gögn frá
           landupplýsingagagnagrunni Landmælinga Finnlands
@@ -2081,6 +2208,14 @@ is:
           %{france}: Inniheldur afleidd gögn frá
           Direction Générale des Impôts (Skattstjóraembættið).
         contributors_fr_france: Frakkland
+        contributors_hr_credit_html: |-
+          %{croatia}: Inniheldur gögn frá %{dgu_link} og %{open_data_portal}
+          (opinberar upplýsingar um Króatíu).
+        contributors_hr_croatia: Króatía
+        contributors_hr_dgu: Jarðfræðistofnun Króatíska ríkisins
+        contributors_hr_dgu_url: https://dgu.gov.hr/
+        contributors_hr_open_data_portal: National Open Data Portal
+        contributors_hr_open_data_portal_url: https://data.gov.hr/
         contributors_nl_credit_html: '%{netherlands}: Inniheldur AND-gögn &copy;,
           2007 (%{and_link})'
         contributors_nl_netherlands: Holland
@@ -2099,7 +2234,9 @@ is:
           (opinberar upplýsingar um Serbíu), 2018.
         contributors_rs_serbia: Serbía
         contributors_rs_rgz: Serbneska jarðfræðistofnunin
+        contributors_rs_rgz_url: https://geosrbija.rs/
         contributors_rs_open_data_portal: National Open Data Portal
+        contributors_rs_open_data_portal_url: https://data.gov.rs/sr/
         contributors_si_credit_html: |-
           %{slovenia}: Inniheldur gögn frá %{gu_link} og %{mkgp_link}
           (opinberar upplýsingar frá Slóveníu).
@@ -2321,6 +2458,7 @@ is:
           ferry: Ferja
           light_rail: Léttlest
           tram: Sporvagn
+          trolleybus: Rafknúinn strætisvagn
           bus: Strætó
           cable_car: Kláflyfta
           chair_lift: Stólalyfta
@@ -2330,11 +2468,13 @@ is:
           admin: Stjórnsýslumörk
           capital: Höfuðborg
           city: Borg
+          orchard: Trjágarður
           vineyard: Vínekra
           forest: Ræktaður skógur
           wood: Skógur
           farmland: Ræktarland
           grass: Gras
+          meadow: Rjóður
           bare_rock: Berar klappir
           sand: Sandur
           golf: Golfvöllur
@@ -2349,6 +2489,7 @@ is:
           scrubland: Kjarrlendi
           lake: Vatn
           reservoir: Uppistöðulón
+          intermittent_water: Ósamfellt vatnasvæði
           glacier: Jökull
           reef: Sker
           wetland: Votlendi
@@ -2374,9 +2515,11 @@ is:
           destination: Umferð leyfileg á ákveðinn áfangastað
           construction: Vegir í byggingu
           bus_stop: Strætisvagnabiðstöð
+          stop: Biðstöð
           bicycle_shop: Hjólaverslun
           bicycle_rental: Reiðhjólaleiga
           bicycle_parking: Reiðhjólastæði
+          bicycle_parking_small: Lítið reiðhjólastæði
           toilets: Salerni
     welcome:
       title: Velkomin!
@@ -2424,6 +2567,7 @@ is:
         automated_edits: Sjálfvirkar breytingar
         automated_edits_url: https://wiki.openstreetmap.org/wiki/Automated_Edits_code_of_conduct
       start_mapping: Hefja kortlagningu
+      continue_authorization: Halda auðkenningu áfram
       add_a_note:
         title: Enginn tími fyrir breytingar? Bættu við athugasemd!
         para_1: Það er auðvelt að bæta við minnispunkti ef þú vilt laga eitthvað smávægilegt
@@ -2529,6 +2673,8 @@ is:
       identifiable: AUÐKENNANLEGT
       private: EINKA
       trackable: REKJANLEGT
+      details_with_tags_html: '%{time_ago} af %{user} í %{tags}'
+      details_without_tags_html: '%{time_ago} af %{user}'
     index:
       public_traces: Allir ferlar
       my_gps_traces: GPS ferlarnir mínir
@@ -2562,6 +2708,10 @@ is:
         other: GPX-skrá með %{count} punktum frá %{user}
       description_without_count: GPX-skrá frá %{user}
   application:
+    basic_auth_disabled: 'Einföld HTTP-auðkenning (Basic Authentication) er óvirk:
+      %{link}'
+    oauth_10a_disabled: 'OAuth 1.0 og 1.0a eru óvirk: %{link}'
+    auth_disabled_link: https://wiki.openstreetmap.org/wiki/2024_authentication_update
     permission_denied: Þú hefur ekki réttindi til að nota þessa aðgerð
     require_cookies:
       cookies_needed: Þú virðist ekki vera með stuðning við vefkökur í vafranum þínum.
@@ -2584,24 +2734,26 @@ is:
       oauth2_authorizations: OAuth 2 auðkenningar
       muted_users: Þaggaðir notendur
     auth_providers:
+      openid_url: OpenID-slóð
+      openid_login_button: Halda áfram
       openid:
         title: Skrá inn með OpenID
-        alt: Skrá inn með OpenID-slóð
+        alt: Táknmerki OpenID
       google:
         title: Skrá inn með Google
-        alt: Skrá inn með Google OpenID-aðgangi
+        alt: Táknmerki Google
       facebook:
         title: Skrá inn með Facebook
-        alt: Skrá inn með Facebook-aðgangi
+        alt: Táknmerki Facebook
       microsoft:
         title: Skrá inn með Microsoft
-        alt: Skrá inn með Microsoft-aðgangi
+        alt: Táknmerki Microsoft
       github:
         title: Skrá inn með GitHub
-        alt: Skrá inn með GitHub-aðgangi
+        alt: Táknmerki GitHub
       wikipedia:
         title: Skrá inn með Wikipedia
-        alt: Skrá inn með Wikipedia-aðgangi
+        alt: Táknmerki Wikipedia
   oauth:
     authorize:
       title: Auðkenndu aðgang að notandaaðganginum þínum
@@ -2642,11 +2794,17 @@ is:
       read_gpx: Lesa einka-GPS-ferlana þína.
       write_gpx: Senda inn GPS feril.
       write_notes: Breyta minnispunktum.
+      write_redactions: Endurskoða kortagögn
       read_email: Lesa tölvupóstfang notanda
+      consume_messages: Lesa, uppfæra stöðu og eyða skilaboðum notenda
+      send_messages: Senda einkaskilaboð til annara notenda
       skip_authorization: Samþykkja forrit sjálfvirkt
+    for_roles:
+      moderator: Þessi heimild er fyrir aðgerðir sem eingöngu tiltækar fyrir umsjónarmenn
   oauth_clients:
     new:
       title: Skrá nýtt forrit
+      disabled: Skráning OAuth 1 forrita hefur verið gerð óvirk
     edit:
       title: Breyta forritinu þínu
     show:
@@ -2692,6 +2850,7 @@ is:
       no_applications_html: Ert þú að nota forrit sem þú myndir vilja skrá til notkunar
         hjá okkur með %{oauth2} staðlinum? Þú verður að skrá vefforritið áður en það
         fer að senda OAuth-beiðnir á þessa þjónustu.
+      oauth_2: OAuth 2
       new: Skrá nýtt forrit
       name: Nafn
       permissions: Heimildir
@@ -2731,38 +2890,60 @@ is:
       title: Auðkenndu forritin mín
       application: Forrit
       permissions: Heimildir
+      last_authorized: Síðast auðkennt
       no_applications_html: Þú hefur ekki ennþá heimilað nein %{oauth2} forrit.
+      oauth_2: OAuth 2
     application:
       revoke: Afturkalla aðgang
       confirm_revoke: Afturkalla aðgang fyrir þetta forrit?
   users:
     new:
       title: Nýskrá
+      tab_title: Nýskrá
+      signup_to_authorize_html: Skráðu þig á OpenStreetMap til að fá aðgang að %{client_app_name}.
       no_auto_account_create: Því miður getum við eki búið til reikning fyrir þig
         sjálfkrafa.
       please_contact_support_html: Hafðu samband við %{support_link} til að fá aðgang
         búinn til - við munum reyna að afgreiða beiðnina eins fljótt og mögulegt er.
       support: aðstoðarteymið
       about:
-        header: Frjálst og breytanlegt
+        header: Frjálst og breytanlegt.
         paragraph_1: Ólíkt öðrum landakortum, er OpenStreetMap gert frá grunni af
           fólki eins og þér, öllum er heimilt að laga það, uppfæra, sækja og nota.
-        paragraph_2: Skráðu þig sem notanda til að geta tekið þátt. Við munum senda
-          þér tölvupóst til staðfestingar á aðgangnum.
+        paragraph_2: Skráðu þig sem notanda til að geta tekið þátt.
+        welcome: Velkomin í OpenStreetMap
+      duplicate_social_email: Ef þú ert þegar með notandaaðgang á OpenStreetMap en
+        óskar eftir að nota utanaðkomandi auðkenningarþjónustu, skaltu skrá þig inn
+        með lykilorðinu þínu og gera viðeigandi breytingar í stillingum notandaaðgangsins
+        þíns.
       display name description: Nafn þitt sem aðrir notendur sjá, þú getur breytt
         því síðar í stillingunum þínum.
       by_signing_up:
+        html: Með því að skrá þig, samþykkir þú %{tou_link}, %{privacy_policy_link}
+          og %{contributor_terms_link} hjá okkur.
         privacy_policy: meðferð persónuupplýsinga
+        privacy_policy_url: https://wiki.osmfoundation.org/wiki/Privacy_Policy
         privacy_policy_title: persónuverndarstefnu OSMF, þar með talinn hlutann um
           tölvupóstföng
+        contributor_terms_url: https://wiki.osmfoundation.org/wiki/Licence/Contributor_Terms
+        contributor_terms: skilmálar vegna framlags
+      tou: notkunarskilmálar
       external auth: 'Auðkenning með þriðja aðila:'
       continue: Nýskrá
       terms accepted: Bestu þakkir fyrir að samþykkja nýju skilmálana vegna framlags
         þíns!
       email_help:
+        privacy_policy: stefna vegna meðferðar persónuupplýsinga
+        privacy_policy_url: https://wiki.osmfoundation.org/wiki/Privacy_Policy
+        privacy_policy_title: persónuverndarstefnu OSMF, þar með talinn hlutann um
+          tölvupóstföng
         html: Netfangið þitt er ekki birt opinberlega, skoðaðu síðuna um %{privacy_policy_link}
           til að sjá nánari upplýsingar.
-      use external auth: Þú getur líka notað utanaðkomandi þjónustur til innskráningar
+      consider_pd_html: Ég lít svo á að framlög mín verði í %{consider_pd_link}.
+      consider_pd: almenningseign
+      consider_pd_url: https://wiki.osmfoundation.org/wiki/Licence_and_Legal_FAQ/Why_would_I_want_my_contributions_to_be_public_domain
+      or: eða
+      use external auth: eða nýskráð þig með utanaðkomandi þjónustu
     terms:
       title: Skilmálar
       heading: Skilmálar
@@ -2798,6 +2979,7 @@ is:
         nýja skilmála vegna framlags (contributor terms). Til að sjá ítarlegri upplýsingar,
         geturðu skoðað %{terms_declined_link}.
       terms_declined_link: þessari wiki síðu
+      terms_declined_url: https://wiki.openstreetmap.org/wiki/Contributor_Terms_Declined
     no_such_user:
       title: Notandi ekki til
       heading: Notandinn %{user} er ekki til
@@ -2818,6 +3000,7 @@ is:
       blocks on me: Bönn gegn mér
       blocks by me: Bönn eftir mig
       create_mute: Þagga þennan notanda
+      destroy_mute: Hætta að þagga niður í þessum notanda
       edit_profile: Breyta notandasíðu
       send message: Senda skilaboð
       diary: Blogg
@@ -2827,6 +3010,9 @@ is:
       remove as friend: Fjarlægja úr vinum
       add as friend: Bæta við sem vini
       mapper since: 'Í kortlagningu síðan:'
+      last map edit: 'Síðasta breyting á korti:'
+      no activity yet: Engin virkni ennþá
+      uid: 'Notandaauðkenni:'
       ct status: 'Skilmálar vegna framlags:'
       ct undecided: Óvíst
       ct declined: Hafnað
@@ -2837,14 +3023,18 @@ is:
       role:
         administrator: Þessi notandi er möppudýr
         moderator: Þessi notandi er prófarkalesari
+        importer: Þessi notandi hefur heimild til innflutnings
         grant:
           administrator: Veita möppudýrsréttindi
           moderator: Veita stjórnandaréttindi
+          importer: Veita aðgang að innflutningi
         revoke:
           administrator: Svifta möppudýrsréttindum
           moderator: Svifta stjórnandaréttindum
+          importer: Afturkalla aðgang að innflutningi
       block_history: Virk bönn
       moderator_history: Úthlutuð bönn (eftir notandann)
+      revoke_all_blocks: Aflétta öllum bönnum
       comments: Athugasemdir
       create_block: Banna þennan notanda
       activate_user: Virkja þennan notanda
@@ -2861,6 +3051,11 @@ is:
     index:
       title: Notendur
       heading: Notendur
+      older: Eldri notendur
+      newer: Nýrri notendur
+      found_users:
+        one: '%{count} notandi fannst'
+        other: '%{count} notendur fundust'
       summary_html: '%{name} var útbúinn frá %{ip_address} þann %{date}'
       summary_no_ip_html: '%{name} útbúinn þann %{date}'
       confirm: Staðfesta valda notendur
@@ -2930,12 +3125,13 @@ is:
       show: Sýna þetta bann
       back: Listi yfir öll bönn
     filter:
-      block_expired: Bannið er þegar útrunnið og er ekki hægt að breyta.
       block_period: Banntíminn verður að vera í forstillingunum.
     create:
       flash: Bjó til bann gegn %{name}.
     update:
       only_creator_can_edit: Aðeins stjórnandinn sem bjó til bannið getur breytt því.
+      only_creator_or_revoker_can_edit: Aðeins þeir umsjónarmenn sem hafa sett bannið
+        geta breytt því.
       success: Banninu var breytt.
     index:
       title: Bönn
@@ -2950,6 +3146,16 @@ is:
       confirm: Staðfestu að þú viljir eyða þessu banni.
       revoke: Eyða banninu
       flash: Banninu var eytt.
+    revoke_all:
+      title: Eyði öllum bönnum á %{block_on}
+      heading_html: Eyði öllum bönnum á %{block_on}
+      empty: '%{name} er ekki með nein virk bönn.'
+      confirm: Ertu viss um að þú viljir aflétta %{active_blocks}?
+      active_blocks:
+        one: '%{count} virkt bann'
+        other: '%{count} virk bönn'
+      revoke: Afturkalla!
+      flash: Öllum virkum bönnum hefur verið aflétt.
     helper:
       time_future_html: Endar eftir %{time}
       until_login: Virkt þangað til notandinn skráir sig inn.
@@ -3004,14 +3210,39 @@ is:
       reason: Ástæða banns
       status: Staða
       revoker_name: Eytt af
+      older: Eldri bönn
+      newer: Nýrri bönn
+    navigation:
+      all_blocks: Öll bönn
+      blocks_on_me: Bönn gegn mér
+      blocks_on_user: Bönn gegn %{user}
+      blocks_by_me: Bönn eftir mig
+      blocks_by_user: Bönn eftir %{user}
+      block: 'Bann #%{id}'
   user_mutes:
     index:
+      title: Þaggaðir notendur
+      my_muted_users: Þaggaðir notendur mínir
+      you_have_muted_n_users:
+        one: Þú hefur þaggað niður í %{count} notanda
+        other: Þú hefur þaggað niður í %{count} notendum
+      user_mute_explainer: Skilaboð frá þögguðum notendum eru sett í sérstakt pósthólf
+        og þú munt ekki fá tilkynningar í tölvupósti.
+      user_mute_admins_and_moderators: Þú getur þaggað niður í stjórnendum og umsjónarfólki
+        en skilaboð þeirra verða ekki þögguð.
       table:
         thead:
           muted_user: Þaggaður notandi
           actions: Aðgerðir
         tbody:
+          unmute: Ekki þagga
           send_message: Senda skilaboð
+    create:
+      notice: Þú þaggaðir niður í %{name}.
+      error: Ekki tókst að þagga niður í %{name}. %{full_message}.
+    destroy:
+      notice: Þú hættir að þagga niður í %{name}.
+      error: Ekki tókst að þagga niður í notandanum. Reyndu aftur.
   notes:
     index:
       title: Minnispunktar sem hafa verið sendir inn eða gerðar athugasemdir við af
@@ -3019,6 +3250,8 @@ is:
       heading: Minnispunktar frá %{user}
       subheading_html: Minnispunktar sem hafa verið %{submitted} eða gerð %{commented}
         við af %{user}
+      subheading_submitted: sendi inn
+      subheading_commented: setti inn athugasemd á
       no_notes: Engir minnispunktar
       id: Auðkenni (ID)
       creator: Búið til af
@@ -3049,6 +3282,7 @@ is:
       reactivate: Virkja aftur
       comment_and_resolve: Athugasemd & leysa
       comment: Athugasemd
+      log_in_to_comment: Skráðu þig inn til að gera athugasemd við þennan minnispunkt
       report_link_html: Ef þessi minnispunktur inniheldur viðkvæmar upplýsingar sem
         þarf að fjarlægja geturðu %{link}.
       other_problems_resolve: Fyrir öll önnur vandamál með minnispunktinn, skaltu
@@ -3061,6 +3295,10 @@ is:
       intro: Fannstu mistök eða eitthvað sem vantar? Láttu aðra kortagerðarmenn vita
         svo hægt sé að laga það. Færðu kortamerkið á réttan stað og skrifaðu minnispunkt
         til að útskýra vandamálið.
+      anonymous_warning_html: Þú ert ekki skráð/ur inn. Notaðu %{log_in} eða %{sign_up}
+        ef þú vilt fá uppfærslur varðandi minnispunktinn þinn.
+      anonymous_warning_log_in: skrá inn
+      anonymous_warning_sign_up: Nýskráðu þig
       advice: Minnispunkturinn þinn er opinber og gæti verið notaður til að uppfæra
         kortið; því ættirðu ekki að setja inn neinar persónulegar upplýsingar, eða
         upplýsingar úr höfundarvörðu efni.
@@ -3079,14 +3317,15 @@ is:
       custom_dimensions: Setja sérsniðnar stærðir
       format: 'Snið:'
       scale: 'Kvarði:'
-      image_dimensions: Myndin mun sýna venjulegt lag á %{width} x %{height}
+      image_dimensions: Myndin mun sýna %{layer} lagið í %{width} x %{height}
       download: Sækja
       short_url: Stutt URL-slóð
       include_marker: Hafa með kortamerkið
       center_marker: Miðja kort á kortamerki
       paste_html: Notaðu þennan HTML kóða til að bæta kortinu á vefsíðu
       view_larger_map: Skoða stærra kort
-      only_standard_layer: Eingöngu er hægt að flytja staðallagið út sem mynd
+      only_standard_layer: Eingöngu er hægt að flytja lögin Staðlað, Hjólakort og
+        Samgöngur út sem mynd
     embed:
       report_problem: Tilkynna vandamál
     key:
@@ -3107,8 +3346,10 @@ is:
           other: Þú ert minna en %{count} fet frá þessum punkti
       base:
         standard: Staðlað
+        cyclosm: CyclOSM
         cycle_map: Hjólakort
         transport_map: Umferðarkort
+        tracestracktop_topo: Tracestrack Topo
         hot: Hjálparstarf
       layers:
         header: Lög á korti
@@ -3126,6 +3367,8 @@ is:
       osm_france: OpenStreetMap Frakklandi
       thunderforest_credit: Kortatíglar frá %{thunderforest_link}
       andy_allan: Andy Allan
+      tracestrack_credit: Kortatíglar frá %{tracestrack_link}
+      tracestrack: Tracestrack
       hotosm_credit: Stíll kortatígla frá %{hotosm_link} hýst af %{osm_france_link}
       hotosm_name: Humanitarian OpenStreetMap teyminu
     site:
@@ -3137,6 +3380,7 @@ is:
       map_data_zoom_in_tooltip: Renndu að til að skoða gögn kortsins
       queryfeature_tooltip: Rannsaka fitjur
       queryfeature_disabled_tooltip: Renndu að til að rannsaka fitjur
+      embed_html_disabled: Ívafið HTML ekki tiltækt fyrir þetta kortalag
     edit_help: Færðu kortið og stilltu aðdrátt inn á staðinn sem þú vilt breyta, smelltu
       síðan hér.
     directions:
index 1209efa6dc60595842b6011bcc192e4be9b1d9d8..a83e2b521b1d8d7af468fc7cecd28d4dd7dc4586 100644 (file)
@@ -3070,7 +3070,6 @@ it:
       show: Visualizza questo blocco
       back: Visualizza tutti i blocchi
     filter:
-      block_expired: Il blocco è già scaduto e non può essere modificato.
       block_period: Il periodo di blocco deve essere uno dei valori selezionabili
         nella lista a tendina.
     create:
index 1676d84ad1b9527ddf243b15c9268adc8d4f7044..6f2693f166de8e0fd474dd6b634da79e4081aaf1 100644 (file)
@@ -2725,7 +2725,6 @@ ja:
       show: このブロックを閲覧
       back: すべてのブロックを閲覧
     filter:
-      block_expired: このブロック期間は既に終了しており、変更できません。
       block_period: ブロック期間はドロップダウンリストから一つ選択してください。
     create:
       flash: 利用者 %{name} をブロックしました。
index 703afbbf080a5cd40a4e991093c45217e69650cd..5f0c6bb7af3501a754756edb720004d07e4c6fce 100644 (file)
@@ -2731,7 +2731,6 @@ ko:
       show: 이 차단 보기
       back: 모든 차단 보기
     filter:
-      block_expired: 차단은 이미 만료되었고 편집할 수 없습니다.
       block_period: 차단 기간은 드롭 다운 목록에서 선택할 수 있는 값 중 하나여야 합니다.
     create:
       flash: '%{name} 사용자를 차단했습니다.'
index 3bfeae8d509861bf9a5a5921e71b59a15cf4278a..b8feb250e9a93955f8c7d8b294a3ad697e706f71 100644 (file)
@@ -388,7 +388,7 @@ ku-Latn:
         relation: eleqe
     start_rjs:
       feature_warning: '%{num_features} taybetmendî bar dibin, dibe ku ev taybetmendî
-        bikin ku geroka te nikaribe bişixule yan jî hêditir bibe. Tu pê bawerî ku
+        bikin ku geroka te nikaribe bişixule yan jî hêdîtir bibe. Tu pê bawer î ku
         tu dixwazî vê daneyê bibînî?'
       load_data: Daneyan Bar Bike
       loading: Tê barkirin...
@@ -1662,8 +1662,8 @@ ku-Latn:
           da aktîvkirin. Ev not nêzîkî %{place} (y)e.'
         commented_note_html: '%{commenter} notekî nexşeyê yê ku te şiroveyek berdabû
           jinûve da aktîvkirin. Ev not nêzîkî %{place} (y)e.'
-      details: Dêtayên zêdetir yên derbarê notê de hûn dikarin ji %{url} bibînin.
-      details_html: Dêtayên zêdetir yên derbarê notê de hûn dikarin ji %{url} bibînin.
+      details: Cewab bide an di derbarê notê de zêdetir hîn bibe ji %{url}.
+      details_html: Cewab bide an di derbarê notê de zêdetir hîn bibe ji %{url}.
     changeset_comment_notification:
       hi: Merheba %{to_user},
       greeting: Merheba,
@@ -1685,14 +1685,14 @@ ku-Latn:
         partial_changeset_with_comment: tevî şiroveya '%{changeset_comment}'
         partial_changeset_with_comment_html: tevî şiroveya '%{changeset_comment}'
         partial_changeset_without_comment: bêyî şirove
-      details: Dêtayên zêdetir yên derbarê desteya guherandinê de hûn dikarin ji %{url}
-        bibînin.
-      details_html: Dêtayên zêdetir yên derbarê desteya guherandinê de hûn dikarin
-        ji %{url} bibînin.
-      unsubscribe: Ji bo ku ji abonetiya rojanekirinên vê desteya guherandinê derbikevî,
-        here %{url} û bitikîne ser "Abonetiyê betal bike".
-      unsubscribe_html: Ji bo ku ji abonetiya rojanekirinên vê desteya guherandinê
-        derbikevî, here %{url} û bitikîne ser "Abonetiyê betal bike".
+      details: Cewab bide an di derbarê desteya guherandinê de zêdetir hîn bibe ji
+        %{url}.
+      details_html: Cewab bide an di derbarê desteya guherandinê de zêdetir hîn bibe
+        ji %{url}.
+      unsubscribe: Tu dikarî ji %{url} ji abonetiya rojanekirinên vê desteya guherandinê
+        derkevî.
+      unsubscribe_html: Tu karî ji %{url} ji abonetiya rojanekirinên vê desteya guherandinê
+        derkevî.
   confirmations:
     confirm:
       heading: E-nameya xwe kontrol bikeǃ
@@ -1765,18 +1765,18 @@ ku-Latn:
         bi hinek kesên nêzîkê xwe re nakevî îrtîbatê?
       people_mapping_nearby: lînka nexşesazên li derdorên nêzîk
     reply:
-      wrong_user: Te wek `%{user}' têket, lê peyamê ku te dixwest were cewabdayîn
-        ji wî/wê bikarhênerê re nehate şandin. Xêra xwe ji bo cewabdanê wekî bikarhênerê
-        rast têbikeve.
+      wrong_user: Te wek `%{user}' têket, lê peyama ku te dixwest were cewabdayîn
+        ji wî bikarhênerê re nehat şandin. Xêra xwe ji bo cewabdanê wekî bikarhênerê
+        rast têkeve.
     show:
       title: Peyamê bixwîne
       reply_button: Bersiv bide
       unread_button: Wek nexwendî nîşan bide
       destroy_button: Jê bibe
       back: Paşve vegere
-      wrong_user: Te wek `%{user}' têket, lê peyamê ku dihate xwestin ku tu wê bixwînî
+      wrong_user: Te wek `%{user}' têket, lê peyama ku dihate xwestin ku tu wê bixwînî
         ji aliyê wî/wê bikarhênerê ve an jî ji wî/wê bikarhênerê re nehatiye şandin.
-        Xêra xwe ji bo xwendinê wekî bikarhênerê rast têbikeve.
+        Xêra xwe ji bo xwendinê wekî bikarhênerê rast têkeve.
     sent_message_summary:
       destroy_button: Jê bibe
     heading:
@@ -1791,7 +1791,7 @@ ku-Latn:
     new:
       title: Şîfreya wenda
       heading: Te şîfreya xwe ji bîr kir?
-      email address: 'Navnîşana E-peyamê:'
+      email address: Adresa e-peyamê
       new password button: Şîfreyê nû bike
       help_text: E-peyama ku te pê xwe qeydkiribû binivîse, em ê ji te re lînkek bişînin
         tu yê bi wê lînkê bikaribî şîfreya xwe nû bikî.
@@ -1848,13 +1848,13 @@ ku-Latn:
     new:
       title: Têkeve
       tab_title: Têkeve
-      email or username: Adrêsa E-peyamê an jî Navê Bikarhêneriyêː
-      password: 'Şîfre:'
+      email or username: Adresa e-peyamê an Navê Bikarhêneriyê
+      password: Şîfre
       remember: Min bi bîr bîne
       lost password link: Te şîfreya xwe winda kir?
       login_button: Têkeve
       register now: Vê gavê xwe qeyd bike
-      with external: Wek alternatîv, ji bo têketinê yek ji van sepanan bi kar bîneː
+      with external: An bi sepaneke alîyê sêyem têkeve
       auth failure: Bibore, bi van dêtayan re tu têneketî.
     destroy:
       title: Derkeve
@@ -2007,8 +2007,9 @@ ku-Latn:
         title: Rêbera ji bo kesên ku nû dest pê kirine
         description: Civata me, ji bo kesên ku nû dest pê kirine rêbertî dike.
       community:
-        title: Foruma civatê
-        description: Cihê hevpar ji bo sohbetên di derbarê OpenStreetMapê de.
+        title: Foruma Alîkarî û Civatê
+        description: Cihê hevpar ji bo gihîna alîkarîyê sohbetên di derbarê OpenStreetMapê
+          de.
       mailing_lists:
         title: Lîsteya E-nameyan
         description: Di lîsteyên e-nameyan yên deverî an jî herêmî yên cur bi cur
@@ -2258,23 +2259,23 @@ ku-Latn:
       oauth2_authorizations: Destûrdarkirinên OAuth 2
     auth_providers:
       openid:
-        title: Bi OpenID'yê têkeve
-        alt: Têketina bi URL'yek OpenID'
+        title: Bi OpenIDyê têkeve
+        alt: Logoya OpenID
       google:
-        title: Bi Google têkeve
-        alt: Têketina bi OpenID ya Googlê
+        title: Bi Googlê têkeve
+        alt: Logoya Googlê
       facebook:
         title: Bi Facebookê têkeve
-        alt: Bi hesabekî Facebookê têkeve
+        alt: Logoya Facebookê
       microsoft:
         title: Bi Microsoftê têkeve
-        alt: Bi hesabê xwe yê Microsoftê têkeve
+        alt: Logoya Microsoftê
       github:
-        title: Bi GitHub'ê têkeve
-        alt: Bi hesabekî GitHubê têbikeve
+        title: Bi GitHubê têkeve
+        alt: Logoya GitHubê
       wikipedia:
-        title: Bi Wîkîpediyayê têkeve
-        alt: Bi hesabekî Wîkîpediyayê têkeve
+        title: Logoya Wîkîpediyayê
+        alt: Logoya Wîkîpediyayê
   oauth:
     authorize:
       title: Ji bo gihîna hesabê xwe selahiyetê bide
@@ -2413,14 +2414,14 @@ ku-Latn:
         çareser bikin.
       support: piştgirî
       about:
-        header: Belaş e û dikare were sererastkirin
+        header: Belaş e û dikare were sererastkirin.
       display name description: Navê te yê ku ji her kesê re tê xuyan. Tu paşê dikarî
         vê navê ji hevyazên xwe biguherînî.
       external auth: 'Teyîdkirina bi aliyên sêyem:'
       continue: Qeyd bibe
       terms accepted: Em spasiya te dikin ji bo ku te şertên beşdariyê yê nû qebûl
         kirǃ
-      use external auth: Wek alternatîv, ji bo têketinê yekî ji van bi kar bîne
+      use external auth: An bi yek ji aplîkasyonên alîyê sêyem qeyd bibe
     terms:
       title: Şertûmerc
       heading: Şertûmerc
@@ -2542,8 +2543,8 @@ ku-Latn:
       option_1: Eger tu di OpenStreetMapê de nû bî, xêra xwe bi vê formê li jêr, ji
         xwe re hesabekî nû çêbike.
       option_2: Heke jixwe hesabekî te hebe, tu dikarî navê xwe yê bikarhêneriyê û
-        şîfreyê xwe binivîsî û têkevî, û piştre jî ji mîhengên bikarhênerê nasnameya
-        (ID'ya) xwe bi hesabê xwe ve girê bidî.
+        şîfreya xwe binivîsî û têkevî, û piştre jî ji mîhengên bikarhênerê nasnameya
+        (IDya) xwe bi hesabê xwe ve girê bidî.
   user_role:
     filter:
       not_a_role: '`%{role}'' ne rolek muteber e.'
@@ -2586,7 +2587,6 @@ ku-Latn:
       show: Vê astengiyê bibîne
       back: Hemû astengiyan bibîne
     filter:
-      block_expired: Wextê astengiyê derbas bûye û nikare were guhartin.
       block_period: Wextê astengiyê, divê yek ji nirxên vê lîsteya ku dikare were
         vekirin be.
     create:
@@ -2729,14 +2729,15 @@ ku-Latn:
       custom_dimensions: Mezinahiyên taybet eyar bike
       format: 'Format:'
       scale: 'Pîvan (miqyas):'
-      image_dimensions: Wêne wê tebeqeya standard li %{width} x %{height} nîşan bide
+      image_dimensions: Wêne wê tebeqeya %{layer} li %{width} x %{height} nîşan bide
       download: Daxîne
       short_url: URLya kurt
       include_marker: Nîşanek deyne
       center_marker: Nîşanê bike merkeza nexşeyê
       paste_html: Ji bo ku di malperê de bi cih bikî HTMLê pê ve bike
       view_larger_map: Nexşeya Mestir Bibîne
-      only_standard_layer: Tenê mezinahiya standard wek rismek dikare were derxistin
+      only_standard_layer: Tenê tebeqeyên Standard, Nexşeya Bisiklêtê û Transportê
+        wek rism kare were derxistin
     embed:
       report_problem: Pirsgirêkek rapor bike
     key:
@@ -2757,7 +2758,7 @@ ku-Latn:
           other: Tu di nava %{count} gavên vê nuqteyê de yî
       base:
         standard: Standard
-        cycle_map: Nexşeya bisiklête
+        cycle_map: Nexşeya bisiklêtê
         transport_map: Nexşeya transportê
         hot: Mirovatî
       layers:
index bfbc4ba8b73d230aa93aea160d4ab46486a97965..10479ebabee645bbd66924bab35ba1b96406c626 100644 (file)
@@ -2763,7 +2763,6 @@ lt:
       show: Peržiūrėti šį blokavimą
       back: Peržiūrėti visus blokavimus
     filter:
-      block_expired: Blokavimo laikas jau baigėsi, todėl negali būti keičiamas.
       block_period: Blokavimo periodo reikšmė turi būti pasirinkta iš iškrentančio
         sąrašo.
     create:
index 9a24f0e615261b980f38c0f3b9275bb247b7f19e..61be609c81cec0acc5c0466caf5241828f4a0fea 100644 (file)
@@ -2072,7 +2072,6 @@ lv:
       show: Apskatīt šo bloku
       back: Skatīt visus blokus
     filter:
-      block_expired: Šis liegums jau ir beidzies un nevar tikt labots.
       block_period: Lieguma periodam jābūt vienam no izvēlamām iespējām krītošajā
         sarakstā.
     create:
index 68a208db8101c5a85bb7f6c420609d3a8f846322..7a77d5fc177ae038596934ea5379ad577a1ae74a 100644 (file)
@@ -1664,13 +1664,19 @@ mk:
       befriend_them: Можете личноста и да ја додадете како пријател на %{befriendurl}.
       befriend_them_html: Можете личноста и да ја додадете како пријател на %{befriendurl}.
     gpx_description:
+      description_with_tags: 'Вашата GPX-податотека %{trace_name} со описот %{trace_description}
+        и следниве ознаки: %{tags}'
       description_with_tags_html: 'Вашата GPX-податотека %{trace_name} со описот %{trace_description}
         и следниве ознаки: %{tags}'
+      description_with_no_tags: Вашата GPX-податотека %{trace_name} со описот %{trace_description}
+        и без ознаки
       description_with_no_tags_html: Вашата GPX-податотека %{trace_name} со описот
         %{trace_description} и без ознаки
     gpx_failure:
       hi: Здраво %{to_user},
       failed_to_import: не можеше да се увезе. Еве ја грешката;
+      more_info: Повеќе информации за неуспесите на увозот на GPX и тоа како да ги
+        одбегнете ќе најдете на %{url}.
       more_info_html: Повеќе информации за неуспесите на увозот на GPX и тоа како
         да ги одбегнете ќе најдете на %{url}.
       import_failures_url: https://wiki.openstreetmap.org/wiki/GPX_Import_Failures?uselang=mk
@@ -1680,6 +1686,8 @@ mk:
       loaded:
         one: успешно вчитано со %{trace_points} од %{count} можни точки.
         other: успешно вчитано со %{trace_points} од %{count} можни точки.
+      trace_location: Вашата трага е достапна на %{trace_url}
+      all_your_traces: Сите ваши успешно подигнати GPX-траги ќе ги најдете на %{url}
       all_your_traces_html: Сите ваши успешно подигнати GPX-траги ќе ги најдете на
         %{url}.
       subject: '[OpenStreetMap] Успешен увоз на GPX-податотека'
@@ -2675,6 +2683,8 @@ mk:
       write_notes: Менување на белешки
       write_redactions: Прикриј податоци за картата
       read_email: Читање на корисничка е-пошта
+      consume_messages: Читајте, менувајте статуси и бришете кориснички пораки
+      send_messages: Испраќајте приватни пораки до други корисници
       skip_authorization: Автоодобрување на прилог
     for_roles:
       moderator: Оваа дозвола е за дејства достапни само за модератори.
@@ -2993,12 +3003,13 @@ mk:
       show: Преглед на овој блок
       back: Преглед на сите блокови
     filter:
-      block_expired: Блокот е веќе истечен и затоа не може да се менува.
       block_period: Периодот на блокада мора да биде со рок избран од паѓачкиот список.
     create:
       flash: Направен е блок на корисникот %{name}.
     update:
       only_creator_can_edit: Само модераторот кој го направил блоков може да го менува.
+      only_creator_or_revoker_can_edit: Овој блок можат да го менуваат само модератори
+        кои го создале или отповикале.
       success: Блокот е изменет.
     index:
       title: Кориснички блокови
@@ -3179,14 +3190,15 @@ mk:
       custom_dimensions: Димензии по ваш избор
       format: 'Формат:'
       scale: 'Размер:'
-      image_dimensions: Сликата ќе го покаже стандардниот слој при %{width} × %{height}
+      image_dimensions: Сликата ќе го покаже слојот %{layer} со %{width} x %{height}
       download: Преземи
       short_url: Кратка URL
       include_marker: Вклучи го бележникот
       center_marker: Сосред. картата на бележникот
       paste_html: Ископирајте го HTML-кодот за да го вметнете во страницата.
       view_larger_map: Преглед на поголема карта
-      only_standard_layer: Само стандардниот слој може да се извезува како слика
+      only_standard_layer: Како слика можат да се извезуваат само слоевите Стандарден,
+        Велосипедска карта и Превоз
     embed:
       report_problem: Пријави проблем
     key:
index aae77d325d7652e0b26236318fe8d6c07e138c39..4aa69ff99086dd97ec8f08c432b6ff608b1d99cc 100644 (file)
@@ -2091,7 +2091,6 @@ ms:
       show: Lihat sekatan ini
       back: Lihat semua sekatan
     filter:
-      block_expired: Sekatan ini sudah luput dan tidak boleh disunting.
       block_period: Tempoh sekatan mestilah salah satu nilai yang boleh dipilih dalam
         senarai juntai bawah ini.
     create:
index 8af954036782151e88986058f29d55f7076e6c56..a5b467e55305f900d7be3e7596bde2db093623af 100644 (file)
@@ -2302,7 +2302,6 @@ nb:
       show: Vis denne blokkeringen
       back: Vis alle blokkeringer
     filter:
-      block_expired: Blokkeringen har allerede utløpt og kan ikke endres.
       block_period: Blokkeringsperioden må være en av verdiene som kan velges fra
         rullegardinen.
     create:
index 0f2311ba4ab5a8551a5c5b79368b1e94b4688947..0a90b62e7e28df4ef56f98455be308b3cfdbc1c0 100644 (file)
@@ -462,9 +462,9 @@ nl:
         way: weg
         relation: relatie
     start_rjs:
-      feature_warning: Er worden %{num_features} objecten geladen, waardoor uw browser
-        traag kan worden of niet meer kan reageren. Weet u zeker dat u deze gegevens
-        wilt weergeven?
+      feature_warning: '%{num_features} functies worden geladen, waardoor uw browser
+        traag kan worden of niet reageert. Weet u zeker dat je deze gegevens wilt
+        weergeven?'
       load_data: Gegevens laden
       loading: Bezig met laden…
     tag_details:
@@ -694,6 +694,8 @@ nl:
       comment: Reactie
       newer_comments: Nieuwere reacties
       older_comments: Oudere reacties
+    new:
+      heading: Een reactie toevoegen aan de volgende dagboekaantekening?
   doorkeeper:
     errors:
       messages:
@@ -2138,7 +2140,7 @@ nl:
         credit_title_html: Hoe OpenStreetMap te vermelden
         credit_1_html: 'Wanneer u OpenStreetMap-gegevens gebruikt, bent u verplicht
           de volgende twee dingen te doen:'
-        credit_2_1: Vermeld OpenStreetMap door onze copyrightmelding te tonen.
+        credit_2_1: Vermeld OpenStreetMap door onze copyrightmelding weer te geven.
         credit_2_2: Maak duidelijk dat de data beschikbaar is onder de Open Database-licentie.
         credit_3_html: Voor de auteursrechtelijke vermelding hanteren wij verschillende
           voorschriften ten aanzien van de manier waarop deze moet worden weergegeven,
@@ -3086,7 +3088,6 @@ nl:
       show: Deze blokkade weergeven
       back: Alle blokkades weergeven
     filter:
-      block_expired: De blokkade is al vervallen en kan niet bijgewerkt worden.
       block_period: De duur van de blokkade moet één van de waarden in het menu zijn.
     create:
       flash: Heeft gebruiker %{name} geblokkeerd.
@@ -3275,14 +3276,15 @@ nl:
       custom_dimensions: Aangepaste afmetingen instellen
       format: 'Formaat:'
       scale: 'Schaal:'
-      image_dimensions: Afbeelding geeft standaardlaag weer op %{width} x %{height}
+      image_dimensions: Afbeelding geeft laag %{layer} weer op %{width} x %{height}
       download: Downloaden
       short_url: Korte URL
       include_marker: Marker opnemen
       center_marker: Kaart centreren op de marker
       paste_html: Kopieer de HTML-code en voeg deze toe aan uw website
       view_larger_map: Grotere kaart weergeven
-      only_standard_layer: Alleen de standaard laag kan worden geëxporteerd als afbeelding
+      only_standard_layer: Alleen de lagen Standaard, Fietskaart en Transportlagen
+        kunnen worden geëxporteerd als afbeelding
     embed:
       report_problem: Een probleem melden
     key:
@@ -3442,7 +3444,7 @@ nl:
       directions_from: Routebeschrijving vanaf hier
       directions_to: Routebeschrijving naar hier
       add_note: Hier een opmerking toevoegen
-      show_address: Adres tonen
+      show_address: Adres weergeven
       query_features: Kaartelementen opvragen
       centre_map: De kaart hier centreren
   redactions:
index ce8463ba0552fd9fdc0fa26e7ca968da5804dd6a..aaf4a90ef2fe0d569aa6751391ce0b1f4945c50e 100644 (file)
@@ -2485,7 +2485,6 @@ nn:
       show: Vis denne blokkeringa
       back: Vis alle blokkeringar
     filter:
-      block_expired: Blokkeringa har allereie utløpt og kan ikkje endrast.
       block_period: Blokkeringsperioden må vere ein av verdia som kan vert frå valde
         rullegardinen.
     create:
index 63393cdaf89c3100fa28d01875dbd1154d39e48e..7b5341362d895186b0b0510660b68d832f658f90 100644 (file)
@@ -2348,8 +2348,6 @@ oc:
         ?
       show: Afichar aqueste blocatge
       back: Veire totes los blocatges
-    filter:
-      block_expired: Lo blocatge a ja expirat e pòt pas èsser modificat.
     create:
       flash: Blocatge creat sus l'utilizaire %{name}.
     update:
index 4ef001e020bcd1a8502f61944ec34e0a3c17b101..3b69092b512bfbe93a3fd00ad60dbebac3ceb2aa 100644 (file)
@@ -2960,7 +2960,6 @@ pl:
       show: Zobacz tę blokadę
       back: Wyświetl wszystkie blokady
     filter:
-      block_expired: Blokada zakończyła się i nie można jej edytować.
       block_period: Długość blokady należy wybrać z listy rozwijanej.
     create:
       flash: Nałożono blokadę na użytkownika %{name}.
index 81451108b601296bf270ed6ad82d45f2be6ad158..a4d652ec2f6a2ea4e6e44ef5470efaa88469dcdc 100644 (file)
@@ -3037,7 +3037,6 @@ pt-PT:
       show: Ver este bloqueio
       back: Ver todos os bloqueios
     filter:
-      block_expired: Este bloqueio já expirou e não pode ser editado.
       block_period: O período de bloqueio tem de corresponder a um dos valores selecionáveis
         da lista.
     create:
index 11b64b6a893e16082f3b994441bcfb4d19b7ca81..74693572b19cef17f920b078dff4185340105b7a 100644 (file)
@@ -3039,7 +3039,6 @@ pt:
       show: Ver esse bloqueio
       back: Ver todos bloqueios
     filter:
-      block_expired: O bloqueio já expirou e não pode mais ser editado.
       block_period: O período de bloqueio deve ser um dos valores selecionáveis na
         lista.
     create:
index 7ee0f7fcfea269ab38aa656fdb6f1444cebbd047..6ce04420683c333c0e8938735eb13d00cf49479f 100644 (file)
@@ -2927,7 +2927,6 @@ ro:
       show: Vezi această blocare
       back: Vezi toate blocările
     filter:
-      block_expired: Blocul a expirat deja și nu poate fi editat.
       block_period: Perioada de blocare trebuie să fie una dintre valorile selectabile
         din lista derulată.
     create:
index ce87fb379890b6abb53142152f8f8fe27d2cae46..7aeef96967ed1db20468878a90530c0d1d0dbeab 100644 (file)
@@ -1067,6 +1067,8 @@ ru:
           gardener: Садовник
           glaziery: Стекольщик
           handicraft: Ремесло
+          hvac: Специалист по микроклиматическим системам
+          metal_construction: Мастерская металлоконструкций
           painter: Художник
           photographer: Фотограф
           plumber: Сантехник
@@ -1075,6 +1077,7 @@ ru:
           shoemaker: Сапожник
           stonemason: Каменщик
           tailor: Портной
+          window_construction: Оконная мастерская
           winery: Винодельня
           "yes": Мастерская
         emergency:
@@ -1085,7 +1088,10 @@ ru:
           fire_extinguisher: Огнетушитель
           fire_water_pond: Пожарный водоём
           landing_site: Место аварийной посадки
+          life_ring: Спасательный круг
           phone: Телефон экстренной связи
+          siren: Аварийная сирена
+          suction_point: Пожарный пирс
           water_tank: Пожарный водоём/резервуар
         highway:
           abandoned: Заброшенная дорога
@@ -1216,6 +1222,7 @@ ru:
           beach_resort: Пляж с насаждениями
           bird_hide: Засидка (пункт скрытого наблюдения за птицами)
           bleachers: Трибуны
+          bowling_alley: Дорожка для боулинга
           common: Общественно-доступная земля
           dance: Танцевальный зал
           dog_park: Площадка для собак
@@ -1225,7 +1232,7 @@ ru:
           fitness_station: Тренажёр
           garden: Сад
           golf_course: Поле для гольфа
-          horse_riding: Ð\9aоннаÑ\8f Ð±Ð°Ð·Ð°
+          horse_riding: Ð¦ÐµÐ½Ñ\82Ñ\80 Ð²ÐµÑ\80Ñ\85овой ÐµÐ·Ð´Ñ\8b
           ice_rink: Каток
           marina: Пристань
           miniature_golf: Минигольф
@@ -3001,7 +3008,6 @@ ru:
       show: Просмотреть эту блокировку
       back: Просмотреть все блокировки
     filter:
-      block_expired: Блокировка уже закончилась и не может быть отредактирована.
       block_period: Период блокировки должен быть одним из значений, выбираемых из
         выпадающего списка.
     create:
index 2c21ee07e7eb157e47f3aed1012f5603883dc17f..c9eefb03cce620ed2940a7bdf72de6900286c70a 100644 (file)
@@ -2903,7 +2903,6 @@ sc:
       show: Pòmpia custu blocu
       back: Pòmpia totu sos blocos
     filter:
-      block_expired: Su blocu est giai iscadidu e non si podet modificare.
       block_period: Su perìodu de blocu depet èssere unu de sos valores chi si podent
         seletzionare dae sa lista a calada.
     create:
index a3308824b4acf4e06b1cc5bf8671427b59591e50..3a61ab83b0cb1756783bf18e334693e0c51acf3b 100644 (file)
@@ -1874,7 +1874,6 @@ scn:
       show: Talìa stu bloccu
       back: Talìa tutti li blocchi
     filter:
-      block_expired: Lu bloccu già scadìu e nun si pò canciari.
       block_period: Lu pirìudu di bloccu havi a èssiri unu dî valuri chi si ponnu
         scègghiri di l'elencu a scinnuta.
     create:
index 5e8369c33ee71524ec8cfd3b8251d578f60ce8ff..19b8ad615ec97ada1a5ea7f2108aa7e10949ed55 100644 (file)
@@ -2729,7 +2729,6 @@ sk:
       show: Zobraziť tento blok
       back: Zobraziť všetky bloky
     filter:
-      block_expired: Blok už vypršal a nemôže byť upravený.
       block_period: Blokovacia doba musí byť jedna z hodnôt voliteľná v roletovom
         menu.
     create:
index 1203d9d3f8901ab46fae04c74347793158b6adfd..a8ac63113d46ee61ec31f686e2e8f2222ded3146 100644 (file)
@@ -2725,6 +2725,8 @@ sl:
       write_notes: Spreminjanje opomb
       write_redactions: Skrij podatke na zemljevidu
       read_email: Branje uporabnikovega e-poštnega naslova
+      consume_messages: Branje, posodabljanje stanja in brisanje uporabniških sporočil
+      send_messages: Pošiljanje zasebnih sporočil drugim uporabnikom
       skip_authorization: Samodejna odobritev aplikacije
     for_roles:
       moderator: To dovoljenje je za dejanja, ki so na voljo samo moderatorjem
@@ -3028,7 +3030,6 @@ sl:
       show: Prikaži blokiranje
       back: Prikaži vsa blokiranja
     filter:
-      block_expired: Blokiranje je že poteklo in ga ni mogoče urejati.
       block_period: Čas blokiranja mora biti ena od izbir s spustnega seznama vrednosti.
     create:
       flash: Ustvarjeno blokiranje uporabnika %{name}.
index c20241b01a326575bd2046693e9f747ddec1bb31..950b04562382457746c89f3c7749c403e978d751 100644 (file)
@@ -1300,7 +1300,6 @@ sr-Latn:
       show: Pogledaj ovu blokadu
       back: Pogledaj sve blokade
     filter:
-      block_expired: Blokada je već istekla i ne može se uređivati.
       block_period: Period blokade mora biti jedna od vrednosti iz padajućeg spiska.
     create:
       flash: Blokiraj korisnika %{name}.
index 623cea7f3784bea67dcf7b3a3c340b051334a044..195c559c52791a838c47d590b709aa6a08923deb 100644 (file)
@@ -2346,7 +2346,6 @@ sr:
       show: Погледај ову блокаду
       back: Погледај све блокаде
     filter:
-      block_expired: Блокада је већ истекла и не може се уређивати.
       block_period: Период блокаде мора бити једна од вредности из падајућег списка.
     create:
       flash: Блокирај корисника %{name}.
index 0730a2fabdb3aba568b504e41dcd0956edd64e89..61c145fdbef2b6baa91a14c09610e75de116e06d 100644 (file)
@@ -444,8 +444,8 @@ sv:
         relation: relation
     start_rjs:
       feature_warning: Laddar %{num_features} kartkomponenter, vilket kan göra din
-        webbläsare långsam eller få den att sluta svara. Är säker på att du vill visa
-        denna data?
+        webbläsare långsam eller få den att sluta svara. Är du säker på att du vill
+        visa denna data?
       load_data: Ladda data
       loading: Läser in …
     tag_details:
@@ -614,6 +614,8 @@ sv:
       title: '%{user}s dagbok | %{title}'
       user_title: '%{user}s dagbok'
       discussion: Diskussion
+      subscribe: Prenumerera
+      unsubscribe: Avsluta prenumeration
       leave_a_comment: Lämna en kommentar
       login_to_leave_a_comment_html: '%{login_link} för att lämna en kommentar'
       login: Logga in
@@ -673,6 +675,8 @@ sv:
       comment: Kommentar
       newer_comments: Nyare kommentarer
       older_comments: Äldre kommentarer
+    new:
+      heading: Lägg en kommentar på följande diskussion om dagboksinlägg?
   doorkeeper:
     errors:
       messages:
@@ -907,6 +911,7 @@ sv:
           college: Högskolebyggnad
           commercial: Kommersiell byggnad
           construction: Byggnad under uppförande
+          cowshed: Kostall
           detached: Fristående hus
           dormitory: Studenthem
           duplex: Dubbelhus
@@ -936,6 +941,7 @@ sv:
           shed: Skjul
           stable: Stall
           static_caravan: Husvagn
+          sty: Stia
           temple: Tempelbyggnad
           terrace: Terrassbyggnad
           train_station: Järnvägsstation
@@ -1643,6 +1649,8 @@ sv:
     intro_text: OpenStreetMap är en karta över världen, skapad av människor som du
       och fri att använda under en öppen licens.
     intro_2_create_account: Skapa ett användarkonto
+    hosting_partners_2024_html: Driften stöds av %{fastly}, %{corpmembers} och andra
+      %{partners}.
     partners_fastly: Fastly
     partners_corpmembers: OSMF-företagsmedlemmar
     partners_partners: partners
@@ -1921,6 +1929,9 @@ sv:
       new password button: Återställ lösenord
       help_text: Ange e-postadressen du använde för att registrera dig så skickar
         vi en länk till den som du kan använda för att återställa ditt lösenord.
+    create:
+      send_paranoid_instructions: Om din e-postadress finns i vår databas kommer du
+        få ett e-postmeddelande för att bekräfta din e-postadress på några minuter.
     edit:
       title: Återställ lösenord
       heading: Återställ lösenord för %{user}
@@ -2140,6 +2151,9 @@ sv:
         contributors_at_cc_by: CC BY
         contributors_at_land_vorarlberg: Förbundsland Vorarlberg
         contributors_at_cc_by_at_with_amendments: CC BY AT med tillägg
+        contributors_au_credit_html: '%{australia}: Inkorporerades eller utvecklades
+          med hjälp av administrativa gränser &copy; %{geoscape_australia_link} licensierades
+          av Samväldet Australien under %{cc_licence_link}.'
         contributors_au_australia: Australien
         contributors_au_geoscape_australia: Geoscape Australien
         contributors_au_cc_licence: Creative Commons Erkännande 4.0 Internationell-licens
@@ -2168,6 +2182,7 @@ sv:
           och %{open_data_portal} (offentlig information om Kroatien)'
         contributors_hr_croatia: Kroatien
         contributors_hr_dgu: Kroatiens statliga geodatiska förvaltning
+        contributors_hr_open_data_portal: Nationella öppen data-portalen
         contributors_nl_credit_html: '%{netherlands}: Innehåller &copy; AND data,
           2007 (%{and_link}).'
         contributors_nl_netherlands: Nederländerna
@@ -2198,6 +2213,7 @@ sv:
         contributors_za_credit_html: '%{south_africa}: Innehåller data från %{ngi_link},
           statens upphovsrätt förbehålls.'
         contributors_za_south_africa: Sydafrika
+        contributors_za_ngi: 'Chief Directorate: National Geo-Spatial Information'
         contributors_gb_credit_html: '%{united_kingdom}: Innehåller Ordnance Survey
           data &copy; Crown copyright and database right 2010-2023.'
         contributors_gb_united_kingdom: Storbritannien
@@ -2644,25 +2660,26 @@ sv:
       oauth2_authorizations: OAuth 2-auktoriseringar
       muted_users: Tystade användare
     auth_providers:
+      openid_url: OpenID-URL
       openid_login_button: Fortsätt
       openid:
         title: Logga in med OpenID
-        alt: Logga in med en OpenID-URL
+        alt: OpenID-logotyp
       google:
         title: Logga in med Google
-        alt: Logga in med ett Google OpenID
+        alt: Google-logotyp
       facebook:
         title: Logga in med Facebook
-        alt: Logga in med ett Facebook-konto
+        alt: Facebook-logotyp
       microsoft:
         title: Logga in med Microsoft
-        alt: Logga in med ett Microsoft-konto
+        alt: Microsoft-logotyp
       github:
         title: Logga in med GitHub
-        alt: Logga in med ett GitHub-Konto
+        alt: GitHub-logotyp
       wikipedia:
         title: Logga in med Wikipedia
-        alt: Logga in med ett Wikipedia-konto
+        alt: Wikipedia-logotyp
   oauth:
     authorize:
       title: Auktorisera tillgång till ditt konto
@@ -2817,9 +2834,14 @@ sv:
           ner och använda.
         paragraph_2: Registrera dig för att börja bidra.
         welcome: Välkommen till OpenStreetMap
+      duplicate_social_email: Om du redan har ett OpenStreetMap-konto och vill använda
+        en identitetsleverantör från en tredjepart, kan du logga in med ditt lösenord
+        och modifiera inställningarna för ditt konto.
       display name description: Ditt offentligt visade användarnamn. Du kan ändra
         detta senare i alternativ.
       by_signing_up:
+        html: Genom att registrera dig accepterar du vår %{tou_link}, %{privacy_policy_link}
+          och %{contributor_terms_link}.
         privacy_policy: integritetspolicy
         privacy_policy_title: OSMFs integritetspolicy inklusive avsnitt om e-postadresser
         contributor_terms: bidragsvillkor
@@ -2829,6 +2851,8 @@ sv:
       terms accepted: Tack för att du accepterat de nya villkoren för bidrag till
         kartan!
       email_help:
+        privacy_policy: integritetspolicy
+        privacy_policy_title: OSMF:s integritetspolicy inkluderingsavsnitt om e-postadresser
         html: Din adress visas inte offentligt, se vår %{privacy_policy_link} för
           mer information.
       consider_pd_html: Jag anser mina bidrag vara i %{consider_pd_link}.
@@ -2900,6 +2924,8 @@ sv:
       remove as friend: Ta bort vän
       add as friend: Lägg till vän
       mapper since: 'Karterar sedan:'
+      last map edit: 'Senaste kartredigering:'
+      no activity yet: Ännu ingen aktivitet
       uid: 'Användar id:'
       ct status: 'Användarvillkor:'
       ct undecided: Ej bestämda
@@ -3016,13 +3042,14 @@ sv:
       show: Visa denna blockering
       back: Visa alla blockeringar
     filter:
-      block_expired: Blockeringen har redan upphört att gälla och kan inte redigeras.
       block_period: Blockeringsperioden måste ha ett av värdena i rullgardinslistan.
     create:
       flash: Upprättade en blockering av användare %{name}.
     update:
       only_creator_can_edit: Bara moderatorn som skapade denna blockering kan redigera
         den.
+      only_creator_or_revoker_can_edit: Endast moderatorer som skapade eller drog
+        tillbaka den här blockeringen kan redigera den.
       success: Blockering uppdaterad.
     index:
       title: Användarblockeringar
@@ -3203,14 +3230,15 @@ sv:
       custom_dimensions: Ange anpassade dimensioner
       format: 'Format:'
       scale: 'Skala:'
-      image_dimensions: Bilden kommer visa standardlager på %{width} x %{height}
+      image_dimensions: Bilden kommer visa lager %{layer} på %{width} x %{height}
       download: Ladda ned
       short_url: Kortlänk
       include_marker: Lägg till markör
       center_marker: Centrera kartan på markören
       paste_html: Klistra in HTML-koden för att publicera på en webbsida
       view_larger_map: Visa större karta
-      only_standard_layer: Endast standardlagret kan exporteras som en bild
+      only_standard_layer: Endast lagrena Standard, Cykelkarta och Transport kan exporteras
+        som en bild
     embed:
       report_problem: Rapportera ett problem
     key:
index cc11d5d456337057a465a2a286d3e695d097b0c1..5633e0b8d24fa8e0c77781b9f1d4a55673f94352 100644 (file)
@@ -2300,7 +2300,6 @@ te:
       show: ఈ నిరోధాన్ని చూడండి
       back: అన్ని నిరోధాలను చూడండి
     filter:
-      block_expired: నిరోధం ఈసరికే ముగిసిపోయింది. దాన్ని సవరించలేరు.
       block_period: నిరోధ కాలం డ్రాప్ డౌన్ జాబితా లోంచి ఎంచుకునే విలువల్లో ఒకటై ఉండాలి.
     create:
       flash: వాడుకరి %{name} పై నిరోధం సృష్టించారు.
index 7d8a2b485638a08817c392cb932aae0c730822c4..12cec4ce360bb7075764dfe385ca888c0675e26f 100644 (file)
@@ -2306,7 +2306,6 @@ th:
       show: ดูรายละเอียดการระงับนี้
       back: แสดงการกีดกันทั้งหมด
     filter:
-      block_expired: การกีดกันนี้สิ้นผลแล้วแก้ไขไม่ได้
       block_period: ดูระยะเวลาที่ระงับ ให้เป็นหนึ่งในค่าที่เลือกไว้จากรายการนี้
     update:
       only_creator_can_edit: การระงับนี้สามารถแก้ไขได้ โดยผู้ดูแลที่เป็นผู้สั่งระงับเองเท่านั้น
index 65aedc8a719ce43806f395da3fdf5c9473d3cda6..15de8f6edee54aa18a04afc18d3e9b5a80015746 100644 (file)
@@ -2039,7 +2039,6 @@ tl:
       show: Tingnan ang hadlang na ito
       back: Tingnan ang lahat ng mga paghadlang
     filter:
-      block_expired: Napaso na ang pagharang at hindi na mababago pa.
       block_period: Ang panahon ng pagharang ay dapat na isa sa mga halagang mapipili
         sa loob ng talaang naibabagsak na paibaba.
     create:
index 655bbd08a5872d05b262954dd9dd2771a48f0fbd..d44f9418bf70ca806035b069cec9a96471c5435e 100644 (file)
@@ -2613,8 +2613,8 @@ tr:
     trace:
       pending: BEKLEMEDE
       count_points:
-        one: '%{count} puan'
-        other: '%{count} puan'
+        one: '%{count} nokta'
+        other: '%{count} nokta'
       more: daha fazla
       trace_details: İz Ayrıntılarını Görüntüle
       view_map: Haritayı Görüntüle
@@ -3057,7 +3057,6 @@ tr:
       show: Bu engellemeyi gör
       back: Tüm engellemeleri göster
     filter:
-      block_expired: Engelin süresi dolmuş ve değiştirilemiyor.
       block_period: Engel süresi, açılır listeden seçilebilen değerlerden biri olmalıdır.
     create:
       flash: '%{name} kullanıcısına engel oluşturuldu.'
index 580c25f90cf311f32f23d412228ab8bf25ab5a0f..3b7647e52df6ccbe6b88ffb44bbc61a352ee18be 100644 (file)
@@ -3100,7 +3100,6 @@ uk:
       show: Переглянути блокування
       back: Переглянути всі блокування
     filter:
-      block_expired: Блокування вже закінчилось і не може бути змінено.
       block_period: Період блокування повинен бути одним зі значень зі списку, що
         розкривається.
     create:
index 53ffcbdffc243cfc1f0ae2db55016e3e19b559c9..3a36ac507e8082a7de4bdc813022c7e9ef19704b 100644 (file)
@@ -2836,7 +2836,6 @@ vi:
       show: Xem tác vụ cấm này
       back: Xem tất cả tác vụ cấm
     filter:
-      block_expired: Không thể sửa đổi tác vụ cấm này vì nó đã hết hạn.
       block_period: Thời hạn cấm phải là một trong những giá trị từ danh sách kéo
         xuống.
     create:
index ba56b9f243bb2c83697102e8861a994c5be826d9..46a72f47a18c5c1319e60d7f39f4d7f80e6e3dc6 100644 (file)
@@ -1649,6 +1649,7 @@ zh-CN:
     tou: 使用条款
     osm_offline: 由于正在进行基本的数据库维护工作,OpenStreetMap 数据库目前处于脱机状态。
     osm_read_only: 由于正在进行基本的数据库维护工作,OpenStreetMap 数据库目前处于只读模式。
+    nothing_to_preview: 无可预览内容。
     donate: 通过给硬件升级基金%{link}支持 OpenStreetMap。
     help: 帮助
     about: 关于
@@ -1689,17 +1690,22 @@ zh-CN:
       befriend_them: 您也可以在 %{befriendurl} 添加他们为朋友。
       befriend_them_html: 您也可以在%{befriendurl}把他们添加为朋友。
     gpx_description:
+      description_with_tags: 看起来您的GPX文件%{trace_name}(描述为%{trace_description},带如下标签:%{tags})
       description_with_tags_html: 您的GPX文件 %{trace_name} ,其描述为 %{trace_description}
         并有以下标签: %{tags}
+      description_with_no_tags: 看起来您的GPX文件%{trace_name}(描述为%{trace_description},不带标签)
       description_with_no_tags_html: 似乎您的GPX文件%{trace_name},描述为%{trace_description},没有标签
     gpx_failure:
       hi: 您好,%{to_user}:
       failed_to_import: 导入失败。下面是错误信息:
+      more_info: 更多有关GPX导入失败的信息及如何避免这些问题,可以在%{url}找到。
       more_info_html: 更多关于 GPX 导入失败的信息,以及如何避免失败可在%{url}找到。
       subject: '[OpenStreetMap] GPX 导入失败'
     gpx_success:
       hi: 您好,%{to_user}:
       loaded: 已成功加载%{count}个可能轨迹点中的%{trace_points}个。
+      trace_location: 您的轨迹可在%{trace_url}查看
+      all_your_traces: 您可以在%{url}找到所有您成功上传的GPX轨迹
       all_your_traces_html: 您可以在 %{url} 找到所有您成功上传的 GPX 轨迹。
       subject: '[OpenStreetMap] GPX 导入成功'
     signup_confirm:
@@ -2225,7 +2231,7 @@ zh-CN:
           trunk: 主干道路
           primary: 一级道路
           secondary: 二级道路
-          unclassified: 无等级道路
+          unclassified: 等外道路
           pedestrian: 人行道
           track: 小路
           bridleway: 马道
@@ -2268,7 +2274,7 @@ zh-CN:
           retail: 零售区
           industrial: 工业区
           commercial: 商业区
-          heathland: 荒原
+          heathland: 欧石楠荒地
           scrubland: 灌木丛林地
           lake: 湖
           reservoir: 水库
@@ -2526,6 +2532,8 @@ zh-CN:
       write_notes: 修改备注
       write_redactions: 隐删地图数据
       read_email: 查看用户邮箱地址
+      consume_messages: 读取、更新状态和删除用户留言
+      send_messages: 向其他用户发送私信
       skip_authorization: 自动核准应用
     for_roles:
       moderator: 此权限仅适用于仲裁员可用的操作。
@@ -2807,12 +2815,12 @@ zh-CN:
       show: 查看此封禁
       back: 查看所有封禁
     filter:
-      block_expired: 这个封禁已经过期,并且不能再编辑。
       block_period: 封禁时期必须是在下拉菜单中可选择的数值之一。
     create:
       flash: 已建立对用户 %{name} 的封禁
     update:
       only_creator_can_edit: 只有执行此封禁的仲裁员才能编辑。
+      only_creator_or_revoker_can_edit: 只有建立或撤销此封禁的仲裁员才能编辑。
       success: 封禁已更新。
     index:
       title: 用户的封禁
@@ -2982,14 +2990,14 @@ zh-CN:
       custom_dimensions: 设定自定义区域
       format: 格式:
       scale: 比例:
-      image_dimensions: 将以%{width} x %{height}的尺寸按标准图层输出图像
+      image_dimensions: 将以%{width} x %{height}的尺寸按%{layer}图层输出图像
       download: 下载
       short_url: 短URL
       include_marker: 包含标记
       center_marker: 以标记作为地图中心
       paste_html: 粘贴HTML以嵌入网站
       view_larger_map: 查看更大的地图
-      only_standard_layer: 只有标准图层可被导出为图片
+      only_standard_layer: 只有标准图层、自行车地图和交通运输图层可被导出为图片
     embed:
       report_problem: 报告问题
     key:
index aa2cdb13525e052adeac7faac8f8c971098ab00f..732499dc25377c4d3c72e71e9c2908d3db9a4fee 100644 (file)
@@ -39,6 +39,7 @@
 # Author: SupaplexTW
 # Author: Tntchn
 # Author: TongcyDai
+# Author: Wayne Su
 # Author: Wehwei
 # Author: WiiUf
 # Author: Winston Sung
@@ -89,7 +90,7 @@ zh-TW:
       messages:
         invalid_email_address: 似乎不是有效的電子郵件信箱地址。
         email_address_not_routable: 不可發送
-        display_name_is_user_n: 不能是「user_n」除非「n」是您的使用者 ID
+        display_name_is_user_n: 不能是「user_n」,除非「n」是你的使用者 ID
       models:
         user_mute:
           is_already_muted: 已忽視
@@ -124,21 +125,21 @@ zh-TW:
       tracetag: 軌跡標籤
       user: 使用者
       user_preference: 使用者偏好設定
-      user_token: 使用者Token
+      user_token: 使用者授權密鑰
       way: 路徑
       way_node: 路徑節點
       way_tag: 路徑標籤
     attributes:
       client_application:
-        name: 名稱(必填)
-        url: 主要應用程式 URL(必填)
+        name: 名稱 (必填)
+        url: 主要應用程式 URL (必填)
         callback_url: 回撥 (Callback) URL
         support_url: 支援 URL
         allow_read_prefs: 讀取使用者偏好設定
         allow_write_prefs: 修改使用者偏好設定
         allow_write_diary: 建立日記、評論和加入好友
         allow_write_api: 修改地圖
-        allow_read_gpx: 讀取個人GPS軌跡
+        allow_read_gpx: 讀取個人 GPS 軌跡
         allow_write_gpx: 上傳 GPS 軌跡
         allow_write_notes: 修改註記
       diary_comment:
@@ -197,7 +198,7 @@ zh-TW:
         pass_crypt_confirmation: 確認密碼
     help:
       doorkeeper/application:
-        confidential: 應用程式會在客戶端密鑰可以維持機密時使用(本地端移動應用程式和單一頁面應用程式不保密)
+        confidential: 應用程式會在客戶端密鑰可以維持機密時使用 (本地端移動應用程式和單一頁面應用程式不保密)
         redirect_uri: 每條 URI 使用一行
       trace:
         tagstring: 以逗點分隔
@@ -270,7 +271,7 @@ zh-TW:
         opened: 新的註記 (在 %{place} 附近)
         commented: 新的評論 (在 %{place} 附近)
         closed: 關閉的註記 (在 %{place} 附近)
-        reopened: 重新開啟的註記(在%{place}附近)
+        reopened: 重新開啟的註記 (在%{place}附近)
       entry:
         comment: 評論
         full: 註記原文
@@ -407,7 +408,7 @@ zh-TW:
         way: 路徑
         relation: 關聯
     start_rjs:
-      feature_warning: 載入 %{num_features} 項物件的資料,可能使您的瀏覽器延遲或無法回應。您是否想要顯示這些資料嗎?
+      feature_warning: 載入 %{num_features} 項物件的資料,可能會使你的瀏覽器延遲或無法回應。你確定要顯示這些資料嗎?
       load_data: 載入資料
       loading: 正在載入…
     tag_details:
@@ -442,7 +443,7 @@ zh-TW:
       previous: « 上一頁
     changeset:
       anonymous: 匿名
-      no_edits: (沒有編輯)
+      no_edits: (沒有編輯)
       view_changeset_details: 檢視變更集詳細資料
     changesets:
       id: ID
@@ -481,7 +482,7 @@ zh-TW:
     no_such_entry:
       title: 沒有這樣的變更集
       heading: 沒有 id 為 %{id} 的項目
-      body: 抱歉,沒有 id 為 %{id} 的變更集。請檢查您的拼字,或者可能是您按到錯誤的連結。
+      body: 抱歉,沒有 id 為 %{id} 的變更集。請檢查你的拼字,或者可能是你按到錯誤的連結。
     show:
       title: 變更集:%{id}
       created: 建立於:%{when}
@@ -510,7 +511,7 @@ zh-TW:
       relations: 關聯 (%{count})
       relations_paginated: 關聯 (%{count} 的 %{x}-%{y})
     timeout:
-      sorry: 很抱歉,請求的變更集清單過長無法讀取。
+      sorry: 很抱歉,請求的變更集清單過長無法讀取。
   changeset_comments:
     comment:
       comment: '由 %{author} 對變更集 #%{changeset_id} 發表的新評論'
@@ -521,22 +522,22 @@ zh-TW:
       title_all: OpenStreetMap 變更集討論
       title_particular: OpenStreetMap 變更集 %{changeset_id} 討論
     timeout:
-      sorry: 很抱歉,請求的變更集評論過長無法讀取
+      sorry: 很抱歉,請求的變更集評論過長無法讀取
   dashboards:
     contact:
       km away: '%{count} 公里遠'
       m away: '%{count} 公尺遠'
       latest_edit_html: 上次編輯於%{ago}:
     popup:
-      your location: 的位置
+      your location: 的位置
       nearby mapper: 附近的製圖者
       friend: 好友
     show:
       title: 我的功能面板
-      no_home_location_html: '%{edit_profile_link}並編輯的家位置,來查看附近的使用者。'
-      edit_your_profile: 編輯的個人檔案
+      no_home_location_html: '%{edit_profile_link}並編輯的家位置,來查看附近的使用者。'
+      edit_your_profile: 編輯的個人檔案
       my friends: 我的好友
-      no friends: 尚未加入任何好友。
+      no friends: 尚未加入任何好友。
       nearby users: 其他附近的使用者
       no nearby users: 附近沒有已加入製圖的使用者。
       friends_changesets: 好友的變更集
@@ -577,7 +578,7 @@ zh-TW:
     no_such_entry:
       title: 沒有這樣的日記項目
       heading: 沒有 id 為 %{id} 的項目
-      body: 抱歉,沒有日記項目或評論的 id 是 %{id}。請檢查您的拼字,或者可能是您按到錯誤的連結。
+      body: 抱歉,沒有日記項目或評論的 id 是 %{id}。請檢查你的拼字,或者可能是你按到錯誤的連結。
     diary_entry:
       posted_by_html: 於 %{created} 由 %{link_user} 以%{language_link}發表。
       updated_at_html: 上一次更新在 %{updated}。
@@ -653,44 +654,44 @@ zh-TW:
             缺少設置導致失敗。
           select_account_for_resource_owner_not_configured: 因 Doorkeeper::OpenidConnect.configure.select_account_for_resource_owner  缺少設置導致失敗。
           subject_not_configured: 因 Doorkeeper::OpenidConnect.configure.subject 缺少配置,產生
-            ID æ¬\8aæ\9d\96失敗。
+            ID æ\8e\88æ¬\8aå¯\86é\91°失敗。
     scopes:
-      address: 查看的實際地址
-      email: 查看您的電子郵件位址
-      openid: 驗證的帳號
-      phone: 查看的電話號碼
-      profile: 查看的個人資訊
+      address: 查看的實際地址
+      email: 查看你的電子郵件信箱
+      openid: 驗證的帳號
+      phone: 查看的電話號碼
+      profile: 查看的個人資訊
   errors:
     contact:
       contact_url_title: 各種聯絡管道說明
       contact: 聯絡
-      contact_the_community_html: 如果您發現有損壞的連結/錯誤,請隨時%{contact_link}OpenStreetMap 社群。並請記下您的請求的確切
-        URL 址。
+      contact_the_community_html: 如果你發現有損壞的連結/錯誤,請隨時%{contact_link}OpenStreetMap 社群。並請記下你的請求的確切
+        URL 址。
     bad_request:
       title: 錯誤請求
-      description: 您在 OpenStreetMap 伺服器上請求的操作無效(HTTP 400)
+      description: 你在 OpenStreetMap 伺服器上請求的操作無效 (HTTP 400)
     forbidden:
       title: Forbidden
-      description: 您在 OpenStreetMap 伺服器上請求的運作僅限管理員使用(HTTP 403)
+      description: 你在 OpenStreetMap 伺服器上請求的運作僅限管理員使用 (HTTP 403}
     internal_server_error:
       title: 應用程式錯誤
-      description: OpenStreetMap 伺服器遇到意外情況,而無法滿足請求(HTTP 500)
+      description: OpenStreetMap 伺服器遇到意外情況,而無法滿足請求 (HTTP 500)
     not_found:
       title: 檔案未找到
-      description: 在 OpenStreetMap 伺服器上找不到該名稱的檔案/目錄/API 操作(HTTP 404)
+      description: 在 OpenStreetMap 伺服器上找不到該名稱的檔案/目錄/API 操作 (HTTP 404)
   friendships:
     make_friend:
       heading: 將 %{user} 加入為好友?
       button: 加入為好友
-      success: '%{name} 現在已成為的好友!'
+      success: '%{name} 現在已成為的好友!'
       failed: 抱歉,無法將 %{name} 加入為好友。
-      already_a_friend: 已經是 %{name} 的好友了。
-      limit_exceeded: 您最近與許多使用者成為朋友。在與其他人成為朋友前請稍候。
+      already_a_friend: 已經是 %{name} 的好友了。
+      limit_exceeded: 你最近與許多使用者成為朋友,要再與其他人成為朋友前請稍候。
     remove_friend:
       heading: 移除好友 %{user}?
       button: 移除好友
-      success: '%{name} 已從的好友中移除。'
-      not_a_friend: '%{name} 並不是的好友。'
+      success: '%{name} 已從的好友中移除。'
+      not_a_friend: '%{name} 並不是的好友。'
   geocoder:
     search:
       title:
@@ -702,43 +703,43 @@ zh-TW:
       prefix:
         aerialway:
           cable_car: 大型纜車
-          chair_lift: å\8d\87é\99\8då\90\8aæ¤\85
-          drag_lift: 上山牽引梯
+          chair_lift: å\90\8aæ¤\85å¼\8fç´¢é\81\93
+          drag_lift: 拖拉式索道
           gondola: 小型纜車
-          magic_carpet: 滑雪升降機
-          platter: 纜椅
-          pylon: 高壓電塔
-          station: ç©ºä¸­çº\9cè»\8a車站
-          t-bar: T å­\97çº\9cæ¤\85
-          "yes": ç©ºä¸­çº\9cç·\9a
+          magic_carpet: 魔毯 (自動步道)
+          platter: 圓盤拖拉式索道
+          pylon: 塔柱
+          station: çº\9c車站
+          t-bar: T å\9e\8bæ¡¿æ\8b\96æ\8b\89å¼\8fç´¢é\81\93
+          "yes": ç©ºä¸­ç´¢é\81\93
         aeroway:
           aerodrome: 機場
-          airstrip: 飛機跑道
+          airstrip: 簡易跑道
           apron: 停機坪
           gate: 登機口
           hangar: 機棚
           helipad: 直升機停機坪
           holding_position: 等待位置
           navigationaid: 航空導航輔助
-          parking_position: 停位置
+          parking_position: 停位置
           runway: 跑道
           taxilane: 滑行道
           taxiway: 滑行道
-          terminal: 航廈
-          windsock: 布製風標
+          terminal: 機場航廈
+          windsock: 風向袋
         amenity:
-          animal_boarding: å\8b\95ç\89©å¯\84宿
+          animal_boarding: å¯µç\89©æ\97\85館
           animal_shelter: 動物收容所
           arts_centre: 藝術中心
-          atm: 提款機
+          atm: 自動提款機
           bank: 銀行
           bar: 酒吧
-          bbq: 烤肉場
+          bbq: 公共烤爐
           bench: 長椅
           bicycle_parking: 自行車停車場
           bicycle_rental: 自行車出租
           bicycle_repair_station: 自行車維修站
-          biergarten: 啤酒庭園
+          biergarten: 露天啤酒場
           blood_bank: 血液銀行
           boat_rental: 船艇出租
           brothel: 妓院
@@ -746,7 +747,7 @@ zh-TW:
           bus_station: 公車站
           cafe: 咖啡廳
           car_rental: 汽車出租
-          car_sharing: 汽車共乘
+          car_sharing: 共享汽車
           car_wash: 洗車
           casino: 賭場
           charging_station: 充電站
@@ -760,7 +761,7 @@ zh-TW:
           courthouse: 法院
           crematorium: 火葬場
           dentist: 牙醫
-          doctors: 醫師
+          doctors: 私人診所
           drinking_water: 飲用水
           driving_school: 駕訓班
           embassy: 大使館
@@ -771,11 +772,11 @@ zh-TW:
           food_court: 美食廣場
           fountain: 噴泉
           fuel: 加油站
-          gambling: 博弈
-          grave_yard: å¢\93å\9c\92
+          gambling: 賭博
+          grave_yard: å®\97æ\95\99å¢\93å\9c°
           grit_bin: 砂箱
           hospital: 醫院
-          hunting_stand: 狩獵
+          hunting_stand: 狩獵小屋
           ice_cream: 冰淇淋
           internet_cafe: 網咖
           kindergarten: 幼兒園
@@ -787,23 +788,23 @@ zh-TW:
           mobile_money_agent: 行動支付代理
           monastery: 修道院
           money_transfer: 匯款
-          motorcycle_parking: æ©\9f車停車場
+          motorcycle_parking: æ\91©æ\89\98車停車場
           music_school: 音樂學校
-          nightclub: 夜總會
-          nursing_home: ç\99\82é¤\8aé\99¢
+          nightclub: 夜
+          nursing_home: ç\85§è­·ä¸­å¿\83
           parking: 停車場
           parking_entrance: 停車場入口
           parking_space: 停車位
-          payment_terminal: äº\92å\8b\95å¼\8f資訊服務站
+          payment_terminal: ä»\98è²»資訊服務站
           pharmacy: 藥房
-          place_of_worship: 禮拜場所
+          place_of_worship: 宗教場所
           police: 警察
           post_box: 郵筒
           post_office: 郵局
           prison: 監獄
           pub: 酒館
-          public_bath: å\85¬å\85±æµ´å ´
-          public_bookcase: 公共書櫃
+          public_bath: å\85¬å\85±æ¾¡å \82
+          public_bookcase: 街頭書櫃
           public_building: 公共建築
           ranger_station: 巡山員站
           recycling: 回收點
@@ -811,16 +812,16 @@ zh-TW:
           sanitary_dump_station: 衛生排污站
           school: 學校
           shelter: 涼亭
-          shower: 淋浴
-          social_centre: 聚會所
+          shower: 淋浴
+          social_centre: 社會團體中心
           social_facility: 社會福利設施
-          studio: 錄音
+          studio: 工作
           swimming_pool: 游泳池
           taxi: 計程車
           telephone: 公共電話
           theatre: 劇院
           toilets: 廁所
-          townhall: 政府大廈
+          townhall: 鄉鎮公所
           training: 訓練設施
           university: 大學
           vehicle_inspection: 車輛檢驗
@@ -830,8 +831,8 @@ zh-TW:
           waste_basket: 垃圾桶
           waste_disposal: 垃圾子車
           waste_dump_site: 垃圾掩埋場
-          watering_place: 集水地點
-          water_point: 水點
+          watering_place: 動物飲水處
+          water_point: 水點
           weighbridge: 地磅
           "yes": 便利設施
         boundary:
@@ -844,29 +845,29 @@ zh-TW:
           "yes": 邊界
         bridge:
           aqueduct: 高架水道
-          boardwalk: æ\9c¨æ\9d¿走道
+          boardwalk: æ\9c¨æ£§走道
           suspension: 吊橋
-          swing: 平
+          swing: 平
           viaduct: 高架橋
-          "yes": 橋
+          "yes": 橋
         building:
           apartment: 公寓
           apartments: 公寓
           barn: 穀倉
           bungalow: 平房
           cabin: 小木屋
-          chapel: 禮拜
+          chapel: 小聖
           church: 教堂建築
           civic: 城市建築
           college: 學院建物
           commercial: 商業建築
-          construction: 在建建築
+          construction: 興建中建築
           cowshed: 牛棚
-          detached: 獨立式住宅
+          detached: 獨立透天厝
           dormitory: 宿舍
           duplex: 複式住宅
           farm: 農舍
-          farm_auxiliary: 附屬農舍建築
+          farm_auxiliary: 農業設施
           garage: 車庫
           garages: 車庫
           greenhouse: 溫室
@@ -882,115 +883,115 @@ zh-TW:
           office: 辦公建築
           public: 公共建築
           residential: 住宅建築
-          retail: 零售建物
+          retail: é\9b¶å\94®å\95\86建ç\89©
           roof: 屋頂
-          ruins: 毀損建築
+          ruins: 毀損建築
           school: 學校建物
-          semidetached_house: 半獨立房
+          semidetached_house: 半獨立房
           service: 服務建築
-          shed: 
+          shed: 工寮
           stable: 馬廄
           static_caravan: 旅行拖車
           sty: 豬圈
-          temple: å»\9få®\87建築
-          terrace: 排屋
+          temple: å¯ºå»\9f建築
+          terrace: 連棟透天厝
           train_station: 車站建物
           university: 大學建築
           warehouse: 倉庫
           "yes": 建築物
         club:
-          scout: 童軍團
+          scout: 童軍團
           sport: 運動俱樂部
           "yes": 俱樂部
         craft:
-          beekeeper: 養蜂人
+          beekeeper: 養蜂人
           blacksmith: 鐵匠
-          brewery: 釀酒
+          brewery: 地方小型釀造
           carpenter: 木匠
-          caterer: å¤\96ç\87´承辦
-          confectionery: ç³\96æ\9e\9c
+          caterer: å®´æ\9c\83承辦
+          confectionery: ç\94\9cé»\9e
           dressmaker: 女裝裁縫
-          electrician: é\9b»å·¥
-          electronics_repair: é\9b»å­\90維修
-          gardener: 園
-          glaziery: ç\8e»ç\92\83å·¥
+          electrician: é\9b»å\8c 
+          electronics_repair: é\9b»å\99¨維修
+          gardener: 園藝師
+          glaziery: ç\8e»ç\92\83å\8c 
           handicraft: 手工藝
-          hvac: 暖通空調製作
-          metal_construction: é\87\91屬建é\80 
-          painter: 畫家
+          hvac: 暖通空調工程
+          metal_construction: é\87\91屬å\8a å·¥
+          painter: 油漆匠
           photographer: 攝影師
-          plumber: 管道
-          roofer: 屋頂
-          sawmill: 鋸木
+          plumber: 水管
+          roofer: 屋頂修繕
+          sawmill: 製材
           shoemaker: 鞋匠
-          stonemason: ç\9f³å·¥
+          stonemason: ç\9f³å\8c 
           tailor: 裁縫師
-          window_construction: çª\97æ\88¶å»ºè¨­
+          window_construction: çª\97æ\88¶å·¥ç¨\8b
           winery: 酒廠
-          "yes": å·¥è\97\9då\93\81åº\97
+          "yes": å°\88業æ\8a\80è¡\93æ\9c\8då\8b\99
         emergency:
-          access_point: 進入點
-          ambulance_station: æ\80¥æ\95\91
-          assembly_point: é\9b\86å\90\88è\99\95
-          defibrillator: 除顫器
+          access_point: 急難地點指示
+          ambulance_station: æ\95\91è­·
+          assembly_point: é\81¿é\9b£å ´æ\89\80
+          defibrillator: 自動心臟去顫器 (AED)
           fire_extinguisher: 滅火器
-          fire_water_pond: 消防水塘
+          fire_water_pond: 消防用水池
           landing_site: 緊急降落點
           life_ring: 緊急救生圈
           phone: 緊急電話
-          siren: 緊急警報器
-          suction_point: 緊急吸水
+          siren: 警報器
+          suction_point: 消防用水抽取
           water_tank: 緊急水箱
         highway:
           abandoned: 廢棄道路
-          bridleway: é¦¬è»\8a
-          bus_guideway: 導向公車道
-          bus_stop: 公車站
-          construction: 建造中道路
+          bridleway: é¨\8e馬
+          bus_guideway: 導軌巴士車道
+          bus_stop: 公車站
+          construction: 興建中道路
           corridor: 走廊
-          crossing: è·¯å\8f£
+          crossing: è¡\8c人穿è¶\8aé\81\93
           cycleway: 自行車道
           elevator: 電梯
-          emergency_access_point: 緊急聯絡點
+          emergency_access_point: 急難地點指示
           emergency_bay: 緊急臨停空間
           footway: 步道
-          ford: 河床便道
-          give_way: 讓路標誌
+          ford: 須涉水
+          give_way: 前方優先標誌
           living_street: 生活街道
           milestone: 里程標
           motorway: 高速公路
-          motorway_junction: 高速公路出口
-          motorway_link: 高速公路聯絡
+          motorway_junction: 高速公路交流道
+          motorway_link: 高速公路
           passing_place: 避車彎
           path: 小徑
           pedestrian: 人行道
           platform: 月台
-          primary: 一級道路
-          primary_link: 一級道路聯絡道
+          primary: 省道
+          primary_link: 省道聯絡道
           proposed: 計畫中道路
           raceway: 賽道
           residential: 住宅區道路
           rest_area: 休息區
           road: 道路
-          secondary: 二級道路
-          secondary_link: 二級道路聯絡道
-          service: 服務道路
+          secondary: 縣道
+          secondary_link: 縣道聯絡道
+          service: 專用道路
           services: 高速公路服務區
-          speed_camera: æ¸¬é\80\9fç\85§ç\9b¸æ©\9f
+          speed_camera: 測速相機
           steps: 階梯
           stop: 停止標誌
           street_lamp: 路燈
-          tertiary: 三級道路
-          tertiary_link: 地區道路聯絡道
+          tertiary: 鄉道
+          tertiary_link: 鄉道聯絡道
           track: 產業道路
           traffic_mirror: 道路反射鏡
           traffic_signals: 交通號誌
-          trailhead: 小徑入口處
-          trunk: 快速
-          trunk_link: 快速道路聯絡
-          turning_circle: 回轉圈
+          trailhead: 步道起點
+          trunk: 快速
+          trunk_link: 快速公路匝
+          turning_circle: 迴轉空間
           turning_loop: 環形迴車道
-          unclassified: 無編制道路
+          unclassified: 未分級道路
           "yes": 道路
         historic:
           aircraft: 歷史飛行機
@@ -1002,98 +1003,98 @@ zh-TW:
           bunker: 掩體
           cannon: 古砲
           castle: 城堡
-          charcoal_pile: 歷史木炭堆
+          charcoal_pile: 古炭窯
           church: 教堂
           city_gate: 城門
           citywalls: 城牆
           fort: 堡壘
-          heritage: 
-          hollow_way: 低窪道路
-          house: 
+          heritage: 
+          hollow_way: 古道
+          house: 
           manor: 莊園
-          memorial: 紀念
+          memorial: 紀念
           milestone: 歷史里程碑
           mine: 礦場
-          mine_shaft: 
-          monument: 古蹟
+          mine_shaft: 
+          monument: 紀念建築
           railway: 歷史鐵路
           roman_road: 羅馬道路
-          ruins: 廢墟
-          rune_stone: ç\9b§æ\81©ç¬¦æ\96\87ç\9f³
-          stone: 石造史蹟
-          tomb: å¢³å¢\93
+          ruins: 遺跡
+          rune_stone: ç\9b§æ\81©ç\9f³å\88»
+          stone: 史蹟石
+          tomb: å¢\93å\9c\92
           tower: 塔
-          wayside_chapel: 路邊教
-          wayside_cross: 路邊十字架
-          wayside_shrine: 路邊神龕
-          wreck: æ®\98骸
+          wayside_chapel: 小聖
+          wayside_cross: 十字架
+          wayside_shrine: 小祠堂
+          wreck: æ²\88è\88¹
           "yes": 古蹟
         junction:
           "yes": 路口
         landuse:
           allotments: 社區農園
           aquaculture: 水產養殖
-          basin: 盆地
-          brownfield: 低污染再利用地
-          cemetery: å¢\93å\9c°
+          basin: 蓄水池
+          brownfield: 棕色地 (受污染放置待恢復重開發地)
+          cemetery: å\85¬å¢\93
           commercial: 商業區
           conservation: 保留區
-          construction: å»ºé\80 ä¸­å\8d\80å\9f\9f
+          construction: å·¥å\9c°
           farmland: 農地
-          farmyard: 農
+          farmyard: 農用設施
           forest: 人工林
-          garages: 
+          garages: 
           grass: 草坪
-          greenfield: ç©ºå\9c°
+          greenfield: ç¶ è\89²å\9c° (æ\9cªä½¿ç\94¨å¾\85é\96\8bç\99¼å\9c°)
           industrial: 工業區
           landfill: 垃圾掩埋場
           meadow: 牧草地
           military: 軍事區
           mine: 礦場
           orchard: 果園
-          plant_nursery: 植物苗圃
-          quarry: 露天礦場
+          plant_nursery: 苗圃
+          quarry: 砂石礦場
           railway: 鐵路用地
-          recreation_ground: é\81\8aæ¨\82å ´
+          recreation_ground: é\81\8aæ¨\82å\8d\80
           religious: 宗教場地
-          reservoir: 蓄水設施
-          reservoir_watershed: 蓄水設施集水區
+          reservoir: 水庫/大型蓄水池
+          reservoir_watershed: 水庫集水區
           residential: 住宅區
-          retail: 零售區
+          retail: é\9b¶å\94®å\95\86å\8d\80
           village_green: 社區綠地
           vineyard: 葡萄園
-          "yes": 土地利用
+          "yes": 土地用途
         leisure:
-          adult_gaming_centre: æ\88\90人é\81\8aæ\88²中心
+          adult_gaming_centre: æ\88\90人é\81\8aæ¨\82中心
           amusement_arcade: 電子遊樂場
-          bandstand: 演奏
-          beach_resort: 海灘遊樂區
-          bird_hide: 賞鳥亭
-          bleachers: 露天看台
-          bowling_alley: 保齡球
-          common: å\85¬å\85±ç\94¨
+          bandstand: 室外音樂
+          beach_resort: 海水浴場
+          bird_hide: 野鳥觀察屋
+          bleachers: 看台
+          bowling_alley: 保齡球球道
+          common: å\85±æ\9c\89
           dance: 舞廳
           dog_park: 遛狗公園
-          firepit: ç\81«å\9d\91
-          fishing: 垂釣
+          firepit: ç\87\9fç\81«å ´
+          fishing: 釣魚
           fitness_centre: 健身中心
-          fitness_station: 健身設施
-          garden: 
-          golf_course: 高爾夫球
-          horse_riding: é¨\8e馬中心
+          fitness_station: 戶外健身區
+          garden: 
+          golf_course: 高爾夫球
+          horse_riding: é¦¬è¡\93中心
           ice_rink: 溜冰場
-          marina: 小船塢
-          miniature_golf: 小型高爾夫球場
-          nature_reserve: è\87ªç\84¶ä¿\9dè­·å\8d\80
+          marina: 碼頭
+          miniature_golf: 迷你高爾夫球場
+          nature_reserve: è\87ªç\84¶ä¿\9dè\82²
           outdoor_seating: 戶外座椅
           park: 公園
           picnic_table: 野餐桌
-          pitch: 運動場
+          pitch: 運動場
           playground: 遊樂區
-          recreation_ground: é\81\8aæ¨\82å ´
+          recreation_ground: é\81\8aæ¨\82å\8d\80
           resort: 度假村
           sauna: 三溫暖
-          slipway: 船臺
+          slipway: 下水滑道
           sports_centre: 運動中心
           stadium: 體育館
           swimming_pool: 游泳池
@@ -1101,55 +1102,55 @@ zh-TW:
           water_park: 水上樂園
           "yes": 休閒
         man_made:
-          adit: 坑
+          adit: 坑
           advertising: 廣告
           antenna: 天線
           avalanche_protection: 雪崩防護
-          beacon: 信標
+          beacon: 信標/燈號
           beam: 橫樑
           beehive: 蜂巢
           breakwater: 防波堤
-          bridge: 橋
+          bridge: 橋
           bunker_silo: 掩體
-          cairn: ç\9f³æ¨\99
+          cairn: ç\96\8aç\9f³
           chimney: 煙囪
           clearcut: 皆伐區域
           communications_tower: 通訊塔
           crane: 起重機
           cross: 十字架
           dolphin: 繫船柱
-          dyke: 堤
-          embankment: 堤
+          dyke: 堤
+          embankment: 
           flagpole: 旗竿
-          gasometer: 儲氣
+          gasometer: 儲氣
           groyne: 丁壩
           kiln: 窯
           lighthouse: 燈塔
           manhole: 人孔
-          mast: æ\9f±
+          mast: æ¡\85
           mine: 礦場
-          mineshaft: 
-          monitoring_station: ç\9b£æ\8e§ç«\99å\8f°
+          mineshaft: 
+          monitoring_station: ç\9b£æ¸¬ç«\99
           petroleum_well: 油井
           pier: 碼頭
           pipeline: 管線
-          pumping_station: 泵站
-          reservoir_covered: 有蓋蓄水槽
+          pumping_station: 泵
+          reservoir_covered: 加蓋水庫/大型蓄水池
           silo: 筒倉
           snow_cannon: 雪砲
           snow_fence: 雪欄
-          storage_tank: 儲油罐
-          street_cabinet: è¡\97æ«\83
-          surveillance: 監視攝影機
+          storage_tank: 儲存槽
+          street_cabinet: è·¯ä¸\8a設æ\96½ç®±
+          surveillance: 監視
           telescope: 望遠鏡
           tower: 塔
-          utility_pole: 電線
-          wastewater_plant: 污水處理
+          utility_pole: 多用途電
+          wastewater_plant: 污水處理
           watermill: 水車
           water_tap: 水龍頭
           water_tower: 水塔
-          water_well: 
-          water_works: 供水設施
+          water_well: 水井
+          water_works: 淨水廠
           windmill: 風車
           works: 工廠
           "yes": 人工設施
@@ -1158,52 +1159,52 @@ zh-TW:
           barracks: 軍營
           bunker: 掩體
           checkpoint: 檢查站
-          trench: 溝渠
+          trench: 壕溝
           "yes": 軍事
         mountain_pass:
           "yes": 埡口
         natural:
           atoll: 環礁
-          bare_rock: 裸露岩石
+          bare_rock: 裸
           bay: 灣
           beach: 海灘
           cape: 海角
           cave_entrance: 洞穴入口
-          cliff: 懸崖
+          cliff: 峭壁
           coastline: 海岸線
           crater: 火山口
           dune: 沙丘
-          fell: 高原荒地
+          fell: 副寒帶、高山草苔
           fjord: 峽灣
-          forest: 管理
+          forest: 人工
           geyser: 間歇泉
           glacier: 冰河
-          grassland: 雜草地
+          grassland: 草原
           heath: 石楠荒地
-          hill: 小山
+          hill: 小山
           hot_spring: 溫泉
           island: 島嶼
           isthmus: 地峽
           land: 陸地
-          marsh: 河川濕地
-          moor: 停泊處
+          marsh: 草沼澤
+          moor: 泥炭沼
           mud: 泥地
           peak: 山峰
           peninsula: 半島
           point: 點
-          reef: 礁
-          ridge: 山脊
+          reef: 
+          ridge: 稜線
           rock: 獨立岩
           saddle: 鞍部
           sand: 沙地
-          scree: ç¢\8eç\9f³å \86
+          scree: ç¢\8eç\9f³å\9d¡
           scrub: 灌木
-          shingle: 礫石
-          spring: 泉
+          shingle: 礫石
+          spring: æ¹§æ³\89
           stone: 巨石
           strait: 海峡
-          tree: 樹木
-          tree_row: 行列樹木
+          tree: 單棵樹
+          tree_row: 一排樹
           tundra: 苔原
           valley: 谷地
           volcano: 火山
@@ -1213,29 +1214,29 @@ zh-TW:
           "yes": 自然地貌
         office:
           accountant: 會計師事務所
-          administrative: 管理局
-          advertising_agency: 廣告代理
+          administrative: 政府機關
+          advertising_agency: 廣告公司
           architect: 建築師事務所
-          association: 協會
+          association: 非營利組織
           company: 公司
-          diplomatic: 使館
+          diplomatic: 外國外交機關
           educational_institution: 教育機構
-          employment_agency: 人力仲介
-          energy_supplier: 能源供應辦公處
+          employment_agency: 就業服務/人材仲介
+          energy_supplier: 能源供應
           estate_agent: 房地產仲介
-          financial: 財務
-          government: 政府辦事處
-          insurance: 保險公司辦公室
-          it: IT 辦公室
-          lawyer: 律師
+          financial: 財務部門
+          government: 政府機關
+          insurance: 保險公司
+          it: 資訊專家
+          lawyer: 律師事務所
           logistics: 物流辦公處
           newspaper: 報社
-          ngo: 非政府組織辦公室
-          notary: 公證人
-          religion: 宗教辦公處
-          research: ç \94究室
+          ngo: 非政府組織
+          notary: 公證人事務所
+          religion: 宗教組織
+          research: ç \94ç\99¼å\96®ä½\8d
           tax_advisor: 稅務顧問
-          telecommunication: 電信業辦事處
+          telecommunication: 電信公司
           travel_agent: 旅行社
           "yes": 辦公室
         place:
@@ -1244,62 +1245,62 @@ zh-TW:
           city: 城市
           city_block: 街區
           country: 國家
-          county: 縣
+          county: 
           farm: 農田
-          hamlet: 村莊
+          hamlet: 聚落
           house: 房屋
           houses: 房屋
-          island: å³¶å¶¼
+          island: å°\8f島
           islet: 礁岩
           isolated_dwelling: 獨立住宅
-          locality: 地
-          municipality: 自治
-          neighbourhood: 
-          plot: 地塊
+          locality: 地
+          municipality: 自治
+          neighbourhood: 鄰近
+          plot: 社區
           postcode: 郵遞區號
-          quarter: 住處
-          region: 區
+          quarter: 地區
+          region: 區
           sea: 海
           square: 廣場
-          state: 
-          subdivision: 分區
-          suburb: 
+          state: 
+          subdivision: 行政分區
+          suburb: 
           town: 鄉鎮
           village: 村里
           "yes": 地點
         railway:
           abandoned: 遺跡鐵路
-          buffer_stop: 緩衝站
-          construction: 建造中鐵路
+          buffer_stop: 止衝擋
+          construction: 興建中鐵路
           disused: 廢棄鐵路
-          funicular: 纜索鐵路
+          funicular: 地索軌道鐵路
           halt: 鐵路招呼站
           junction: 鐵路交匯處
           level_crossing: 平交道
           light_rail: 輕軌
-          miniature: å¾®å\9e\8bé\90µè·¯
+          miniature: å°\8fç\81«è»\8a
           monorail: 單軌鐵路
           narrow_gauge: 窄軌鐵路
           platform: 鐵路月臺
-          preserved: 保鐵路
+          preserved: 保存線鐵路
           proposed: 規劃中鐵路
           rail: 鐵路
-          spur: 鐵路
+          spur: 鐵路專用側
           station: 鐵路車站
-          stop: 鐵路招呼站
+          stop: 鐵路停靠點
           subway: 地下鐵
           subway_entrance: 地下鐵出入口
           switch: 道岔
           tram: 路面電車軌道
           tram_stop: 路面電車停靠站
-          turntable: 轉
-          yard: 鐵路
+          turntable: 轉車台
+          yard: 鐵路調車
         shop:
-          agrarian: 農業品店
-          alcohol: 酒
+          agrarian: 農業品店
+          alcohol: 酒舖 (未開瓶)
           antiques: 古董店
-          appliance: 家用電器
-          art: 藝品店
+          appliance: 家用電器
+          art: 藝品店
           baby_goods: 嬰兒用品
           bag: 包包店
           bakery: 麵包店
@@ -1308,82 +1309,82 @@ zh-TW:
           bed: 寢具
           beverages: 飲料店
           bicycle: 自行車店
-          bookmaker: 投注處
+          bookmaker: 簽注站
           books: 書店
           boutique: 精品店
           butcher: 肉品店
-          car: 汽車
+          car: 汽車經銷商
           car_parts: 汽車零件
           car_repair: 汽車維修
           carpet: 地毯店
-          charity: 慈善商店
-          cheese: 起士店
+          charity: 公益商店
+          cheese: 起士店
           chemist: 藥妝店
-          chocolate: 巧克力店
+          chocolate: 巧克力店
           clothes: 服飾店
-          coffee: 咖啡店
-          computer: é\9b»è\85¦å\95\86åº\97
+          coffee: 咖啡豆專賣
+          computer: 電腦店
           confectionery: 甜點店
-          convenience: 便利商店
+          convenience: 便利超商
           copyshop: 複印店
           cosmetics: 化妝品店
-          craft: 工藝品供應
+          craft: 工藝用品
           curtain: 窗簾店
-          dairy: 乳品店
-          deli: 高級食
+          dairy: 乳品店
+          deli: 高級食
           department_store: 百貨商店
           discount: 特價商品店
           doityourself: DIY 用品店
-          dry_cleaning: 乾洗
+          dry_cleaning: 乾洗
           e-cigarette: 電子菸店
-          electronics: é\9b»å­\90æ\9d\90æ\96\99
+          electronics: é\9b»å\99¨
           erotic: 情趣用品店
           estate_agent: 房地產仲介
           fabric: 布料行
-          farm: 農場商
-          fashion: æ\99\82è£\9d
-          fishing: 釣魚用品
+          farm: 農產直銷
+          fashion: æµ\81è¡\8cæ\9c\8d飾
+          fishing: 釣
           florist: 花店
           food: 食品店
           frame: 相框店
           funeral_directors: 葬儀社
           furniture: 傢俱行
           garden_centre: 園藝中心
-          gas: 加油站
+          gas: 瓦斯行
           general: 一般商店
           gift: 禮品店
-          greengrocer: 生鮮食品
+          greengrocer: 果菜
           grocery: 雜貨店
           hairdresser: 理髮店
           hardware: 五金行
           health_food: 保健食品店
           hearing_aids: 助聽器
-          herbalist: 藥草供應商
-          hifi: 音響店
-          houseware: 生活用品店
+          herbalist: 藥草店/中藥行
+          hifi: 視聽音響店
+          houseware: 居家用品店
           ice_cream: 冰淇淋店
-          interior_decoration: 室內裝潢
-          jewelry: 珠寶店
+          interior_decoration: 室內擺飾
+          jewelry: 珠寶飾品
           kiosk: 販售亭
           kitchen: 廚房用品店
           laundry: 洗衣店
           locksmith: 鎖店
           lottery: 樂透
-          mall: 購物商場
+          mall: 購物中心
           massage: 按摩店
-          medical_supply: 醫療用品
+          medical_supply: 醫療器材與輔具
           mobile_phone: 行動通訊行
           money_lender: 貸款
-          motorcycle: æ©\9fè»\8aè¡\8c
-          motorcycle_repair: æ©\9f車維修行
+          motorcycle: æ\91©æ\89\98è»\8aç¶\93é\8a·å\95\86
+          motorcycle_repair: æ\91©æ\89\98車維修行
           music: 唱片行
           musical_instrument: 樂器
-          newsagent: æ\96°è\81\9e代ç\90\86å\95\86
-          nutrition_supplements: 營養補品
-          optician: 驗光師
+          newsagent: æ\9b¸å ±æ\94¤
+          nutrition_supplements: 營養補
+          optician: 眼鏡行
           organic: 有機食品店
           outdoor: 戶外用品店
-          paint: 油漆
+          paint: 油漆
           pastry: 糕餅店
           pawnbroker: 當鋪
           perfumery: 香水店
@@ -1392,68 +1393,68 @@ zh-TW:
           photo: 照相館
           seafood: 海產
           second_hand: 二手商品店
-          sewing: 縫紉
+          sewing: 縫紉材料行
           shoes: 鞋店
           sports: 體育用品店
           stationery: 文具店
-          storage_rental: 迷你倉
-          supermarket: 超級市場
+          storage_rental: 出租倉庫
+          supermarket: 超
           tailor: 裁縫店
           tattoo: 刺青屋
-          tea: è\8c¶è\88\96
+          tea: è\8c¶è\91\89è¡\8c
           ticket: 售票處
-          tobacco: 菸草販賣
+          tobacco: 香菸店
           toys: 玩具店
           travel_agency: 旅行社
-          tyres: è¼ªè\83\8e販å\94®
+          tyres: è¼ªè\83\8eè¡\8c
           vacant: 空置店舖
-          variety_store: 雜貨
+          variety_store: 均一價商
           video: 影音店
           video_games: 電子遊戲專賣店
-          wholesale: 批發
-          wine: 葡萄酒
+          wholesale: 批發量販店
+          wine: 葡萄酒
           "yes": 商店
         tourism:
-          alpine_hut: 山
+          alpine_hut: 山
           apartment: 假日公寓
-          artwork: 美工
+          artwork: 藝術品
           attraction: 景點
-          bed_and_breakfast: 家庭旅館
-          cabin: 旅遊小
-          camp_pitch: 營
+          bed_and_breakfast: B&B
+          cabin: 小木
+          camp_pitch: 營
           camp_site: 營地
           caravan_site: RV 宿營區
           chalet: 小木屋
-          gallery: 圖庫
-          guest_house: 賓館
-          hostel: 旅舍
-          hotel: 酒店
-          information: 旅遊中心
+          gallery: 藝廊
+          guest_house: 民宿
+          hostel: 青年旅舍
+          hotel: 旅館
+          information: 資訊服務處
           motel: 汽車旅館
           museum: 博物館
-          picnic_site: é\87\8eé¤\90å\9c°
+          picnic_site: é\87\8eé¤\90å\8d\80
           theme_park: 主題公園
           viewpoint: 觀景點
-          wilderness_hut: 荒野小
+          wilderness_hut: 避難山
           zoo: 動物園
         tunnel:
-          building_passage: 建築物通道
+          building_passage: 建築物穿堂
           culvert: 涵管
           "yes": 隧道
         waterway:
           artificial: 人工水道
-          boatyard: è\88¹å¡¢
-          canal: 運河
+          boatyard: è\88¹å» 
+          canal: 運河/大水渠
           dam: 水壩
           derelict_canal: 廢棄運河
-          ditch: å°\8fæº\9d渠
-          dock: 碼頭
+          ditch: å\9c\9fæº\9d
+          dock: 船塢
           drain: 溝渠
-          lock: 水門
-          lock_gate: 船閘
+          lock: 船閘
+          lock_gate: 閘門
           mooring: 停泊處
           rapids: 急流
-          river: 河
+          river: 河
           stream: 小溪
           wadi: 乾河
           waterfall: 瀑布
@@ -1462,18 +1463,18 @@ zh-TW:
       admin_levels:
         level2: 國界
         level3: 區界
-        level4: 
+        level4: 
         level5: 區界
         level6: 縣界
-        level7: 自治
+        level7: 自治
         level8: 市界
         level9: 村里界
-        level10: 區邊界
-        level11: 社區邊
+        level10: 區邊界
+        level11: 鄰近區
       types:
         cities: 城市
         towns: 鄉鎮
-        places: 地
+        places: 地
     results:
       no_results: 找不到結果
       more_results: 更多結果
@@ -1500,7 +1501,7 @@ zh-TW:
       reported_item: 已回報項目
       states:
         ignored: 已忽略
-        open: 開
+        open: 開
         resolved: 已解決
     show:
       title: '%{status} 問題 #%{issue_id}'
@@ -1537,17 +1538,17 @@ zh-TW:
         note: '註記 #%{note_id}'
   issue_comments:
     create:
-      comment_created: 的評論已成功建立
-      issue_reassigned: 已建立的評論,並重新分配問題
+      comment_created: 的評論已成功建立
+      issue_reassigned: 已建立的評論,並重新分配問題
   reports:
     new:
       title_html: 回報 %{link}
       missing_params: 無法建立新的回報
       disclaimer:
-        intro: 發送的回報給站台仲裁員前,請確認:
-        not_just_mistake: 確定了該問題內容並非誤會
-        unable_to_fix: 您無法自行或在您的社群成員協助下修正問題
-        resolve_with_user: 已準備嘗試解決使用者關注的問題
+        intro: 發送的回報給站台仲裁員前,請確認:
+        not_just_mistake: 確定了該問題內容並非誤會
+        unable_to_fix: 你無法自行、或在社群成員協助下修正問題
+        resolve_with_user: 已準備嘗試解決使用者關注的問題
       categories:
         diary_entry:
           spam_label: 此日記項目為/含有垃圾訊息
@@ -1571,7 +1572,7 @@ zh-TW:
           abusive_label: 此註記有辱駡內容
           other_label: 其它
     create:
-      successful_report: 已成功登記的回報
+      successful_report: 已成功登記的回報
       provide_details: 請提供所需的詳情
   layouts:
     project_name:
@@ -1597,7 +1598,7 @@ zh-TW:
     edit_with: 以 %{editor} 編輯
     tag_line: 自由的 wiki 世界地圖
     intro_header: 歡迎來到 OpenStreetMap!
-    intro_text: OpenStreetMap 是一幅世界地圖,由像您這樣的人們所建立,在開放授權下可以自由使用。
+    intro_text: OpenStreetMap 是一份全世界的地圖,由像你這樣的人們所建立,在開放授權下可以自由使用。
     intro_2_create_account: 建立使用者帳號
     hosting_partners_2024_html: 由%{fastly}、%{corpmembers},和其他%{partners}支援代管。
     partners_fastly: Fastly
@@ -1606,6 +1607,7 @@ zh-TW:
     tou: 使用條款
     osm_offline: OpenStreetMap 資料庫目前正在離線,直到必要的資料庫維護工作完成為止。
     osm_read_only: OpenStreetMap 資料庫目前處於唯讀模式,直到必要的資料庫維護工作完成為止。
+    nothing_to_preview: 無可預覽內容。
     donate: 以 %{link} 給硬體升級基金來支援 OpenStreetMap。
     help: 說明
     about: 關於
@@ -1623,34 +1625,37 @@ zh-TW:
     diary_comment_notification:
       description: 'OpenStreetMap 日記項目 #%{id}'
       subject: '[OpenStreetMap] %{user} 已評論日記項目'
-      hi: '%{to_user} 好,'
+      hi: '%{to_user} 好,'
       header: '%{from_user} 評論主旨為 %{subject} 的 OpenStreetMap 日記項目:'
       header_html: '%{from_user} 評論主旨為 %{subject} 的 OpenStreetMap 日記項目:'
-      footer: 也可以在 %{readurl} 閱讀評論,並且在 %{commenturl} 留下評論,或在 %{replyurl} 發送訊息給作者
-      footer_html: 也可以在 %{readurl} 閱讀評論,並且在 %{commenturl} 留下評論,或在 %{replyurl} 發送訊息給作者
-      footer_unsubscribe: 可以在%{unsubscribeurl}取消訂閱討論
-      footer_unsubscribe_html: 可以在%{unsubscribeurl}取消訂閱討論
+      footer: 也可以在 %{readurl} 閱讀評論,並且在 %{commenturl} 留下評論,或在 %{replyurl} 發送訊息給作者
+      footer_html: 也可以在 %{readurl} 閱讀評論,並且在 %{commenturl} 留下評論,或在 %{replyurl} 發送訊息給作者
+      footer_unsubscribe: 可以在%{unsubscribeurl}取消訂閱討論
+      footer_unsubscribe_html: 可以在%{unsubscribeurl}取消訂閱討論
     message_notification:
       subject: '[OpenStreetMap] %{message_title}'
       hi: '%{to_user} 您好,'
-      header: '%{from_user} 透過 OpenStreetMap 寄給主旨為 %{subject} 的訊息:'
-      header_html: '%{from_user} 透過 OpenStreetMap 寄給主旨為 %{subject} 的訊息:'
-      footer: 也可以在 %{readurl} 閱讀訊息,並且在 %{replyurl} 發送訊息給作者
-      footer_html: 也可以在 %{readurl} 閱讀訊息,並且在 %{replyurl} 發送訊息給作者
+      header: '%{from_user} 透過 OpenStreetMap 寄給主旨為 %{subject} 的訊息:'
+      header_html: '%{from_user} 透過 OpenStreetMap 寄給主旨為 %{subject} 的訊息:'
+      footer: 也可以在 %{readurl} 閱讀訊息,並且在 %{replyurl} 發送訊息給作者
+      footer_html: 也可以在 %{readurl} 閱讀訊息,並且在 %{replyurl} 發送訊息給作者
     friendship_notification:
       hi: 嗨 %{to_user},
-      subject: '[OpenStreetMap] %{user} 將您加入為好友'
-      had_added_you: '%{user} 已在 OpenStreetMap 將您加入為好友。'
-      see_their_profile: 可以在 %{userurl} 查看他的基本資料。
-      see_their_profile_html: 可以在 %{userurl} 查看他的基本資料。
-      befriend_them: 可以在 %{befriendurl} 把他加入為好友。
-      befriend_them_html: 可以在 %{befriendurl} 把他加入為好友。
+      subject: '[OpenStreetMap] %{user} 將你加為好友'
+      had_added_you: '%{user} 已在 OpenStreetMap 將你加為好友。'
+      see_their_profile: 可以在 %{userurl} 查看他的基本資料。
+      see_their_profile_html: 可以在 %{userurl} 查看他的基本資料。
+      befriend_them: 可以在 %{befriendurl} 把他加入為好友。
+      befriend_them_html: 可以在 %{befriendurl} 把他加入為好友。
     gpx_description:
-      description_with_tags_html: 看起來似乎是您的 GPX 檔案%{trace_name}帶有%{trace_description}描述而且沒有標籤:%{tags}
-      description_with_no_tags_html: 看起來似乎是您的 GPX 檔案%{trace_name}帶有%{trace_description}描述而且沒有標籤
+      description_with_tags: 看起來似乎是你的 GPX 檔案%{trace_name}帶有%{trace_description}描述而且沒有標籤:%{tags}
+      description_with_tags_html: 看起來似乎是你的 GPX 檔案%{trace_name}帶有%{trace_description}描述而且沒有標籤:%{tags}
+      description_with_no_tags: 看起來似乎是你的 GPX 檔案%{trace_name}帶有%{trace_description}描述而且沒有標籤
+      description_with_no_tags_html: 看起來似乎是你的 GPX 檔案%{trace_name}帶有%{trace_description}描述而且沒有標籤
     gpx_failure:
-      hi: '%{to_user} 好,'
+      hi: '%{to_user} 好,'
       failed_to_import: 看來匯入失敗。錯誤訊息為:
+      more_info: 更多關於 GPX 匯入失敗的資訊與如何避免,可在 %{url} 查詢。
       more_info_html: 更多關於 GPX 匯入失敗的資訊與如何避免,可在 %{url} 查詢。
       subject: '[OpenStreetMap] GPX 匯入失敗'
     gpx_success:
@@ -1658,35 +1663,37 @@ zh-TW:
       loaded:
         one: 成功載入 %{count} 個可能軌跡點中的 %{trace_points} 個。
         other: 成功載入 %{count} 個可能軌跡點中的 %{trace_points} 個。
-      all_your_traces_html: 您可以在 %{url} 找到所有您上傳成功的 GPX 軌跡。
+      trace_location: 你的軌跡已在 %{trace_url} 上可用
+      all_your_traces: 你可以在 %{url} 找到所有上傳成功的 GPX 軌跡
+      all_your_traces_html: 你可以在 %{url} 找到所有上傳成功的 GPX 軌跡。
       subject: '[OpenStreetMap] GPX 匯入成功'
     signup_confirm:
       subject: '[OpenStreetMap] 歡迎加入 OpenStreetMap'
-      greeting: 好!
-      created: 有人 (希望是) 剛在 %{site_url} 建立了帳號。
-      confirm: 在我們作出任何動作之前,我們需要確認這是提出的要求。如果確實是這樣,請按以下連結,以確認你的帳號:
+      greeting: 好!
+      created: 有人 (希望是) 剛在 %{site_url} 建立了帳號。
+      confirm: 在我們作出任何動作之前,我們需要確認這是提出的要求。如果確實是這樣,請按以下連結,以確認你的帳號:
       welcome: 在確認你的帳號後,我們將提供一些額外的訊息,幫助你開始使用 OpenStreetMap。
     email_confirm:
-      subject: '[OpenStreetMap] 確認您的電子郵件地址'
+      subject: '[OpenStreetMap] 確認你的電子郵件信箱'
       greeting: 您好,
-      hopefully_you: 有人 (希望是您) 希望在 %{server_url} 更改電子郵件地址至 %{new_address} 。
-      click_the_link: 如果這是,請按下列連結確認此變更。
+      hopefully_you: 有人 (希望是你) 想在 %{server_url} 更改電子郵件信箱為 %{new_address} 。
+      click_the_link: 如果這是,請按下列連結確認此變更。
     lost_password:
       subject: '[OpenStreetMap] 密碼重設要求'
-      greeting: 好,
-      hopefully_you: 有人 (或許是您) 要求將以此電子郵件地址註冊的 openstreetmap.org 帳號,重設密碼。
-      click_the_link: 如果這是您,請按下列連結重設您的密碼。
+      greeting: 好,
+      hopefully_you: 有人 (或許是你) 要求將這個電子郵件信箱註冊的 openstreetmap.org 帳號重設密碼。
+      click_the_link: 如果這是你,請按下列連結重設密碼。
     note_comment_notification:
       description: 'OpenStreetMap 註記 #%{id}'
       anonymous: 匿名使用者
-      greeting: 好,
+      greeting: 好,
       commented:
-        subject_own: '[OpenStreetMap] %{commenter} å\9c¨æ\82¨ç\9a\84註è¨\98評論'
-        subject_other: '[OpenStreetMap] %{commenter} å°±æ\82¨æ\84\9fè\88\88趣ç\9a\84註è¨\98評論'
-        your_note: '%{commenter} å\9c¨ %{place} é\99\84è¿\91ç\9a\84å\9c°å\9c\96註è¨\98評論。'
-        your_note_html: '%{commenter} å\9c¨ %{place} é\99\84è¿\91ç\9a\84å\9c°å\9c\96註è¨\98評論。'
-        commented_note: '%{commenter} å\9c¨ä½ æ\84\9fè\88\88趣ç\9a\84å\9c°å\9c\96註è¨\98評論。該註記在 %{place} 附近。'
-        commented_note_html: '%{commenter} å\9c¨ä½ æ\84\9fè\88\88趣ç\9a\84å\9c°å\9c\96註è¨\98評論。該註記在 %{place} 附近。'
+        subject_own: '[OpenStreetMap] %{commenter} å°\8dä½ ç\9a\84註è¨\98å\81\9aäº\86評論'
+        subject_other: '[OpenStreetMap] %{commenter} å°\8dä½ æ\84\9fè\88\88趣ç\9a\84註è¨\98å\81\9aäº\86評論'
+        your_note: '%{commenter} å°\8d %{place} é\99\84è¿\91ç\9a\84å\9c°å\9c\96註è¨\98å\81\9aäº\86評論。'
+        your_note_html: '%{commenter} å°\8d %{place} é\99\84è¿\91ç\9a\84å\9c°å\9c\96註è¨\98å\81\9aäº\86評論。'
+        commented_note: '%{commenter} å°\8dä½ æ\84\9fè\88\88趣ç\9a\84å\9c°å\9c\96註è¨\98å\81\9aäº\86評論。該註記在 %{place} 附近。'
+        commented_note_html: '%{commenter} å°\8dä½ æ\84\9fè\88\88趣ç\9a\84å\9c°å\9c\96註è¨\98å\81\9aäº\86評論。該註記在 %{place} 附近。'
       closed:
         subject_own: '[OpenStreetMap] %{commenter} 解決你其中一筆註記 %{commenter}'
         subject_other: '[OpenStreetMap]%{commenter} 已解決一項你感興趣的註記'
@@ -1699,8 +1706,8 @@ zh-TW:
         subject_other: '[OpenStreetMap] %{commenter} 再次開啟你感興趣的註記。'
         your_note: '%{commenter} 已經再次開啟你其中一筆接近 %{place} 的地圖註記。'
         your_note_html: '%{commenter} 已經再次開啟你其中一筆接近 %{place} 的地圖註記。'
-        commented_note: '%{commenter} 重新開啟了一個曾評論的地圖註記。該註記位於 %{place} 附近。'
-        commented_note_html: '%{commenter} 重新開啟了一個曾評論的地圖註記。該註記位於 %{place} 附近。'
+        commented_note: '%{commenter} 重新開啟了一個曾評論的地圖註記。該註記位於 %{place} 附近。'
+        commented_note_html: '%{commenter} 重新開啟了一個曾評論的地圖註記。該註記位於 %{place} 附近。'
       details: 關於註記的更多詳細資料可在 %{url} 找到。
       details_html: 在%{url}回覆或是瞭解更多有關註記的訊息。
     changeset_comment_notification:
@@ -1708,43 +1715,43 @@ zh-TW:
       hi: 嗨 %{to_user},
       greeting: 您好,
       commented:
-        subject_own: '[OpenStreetMap] %{commenter} å\9c¨æ\82¨ç\9a\84è®\8aæ\9b´é\9b\86è©\95è«\96'
-        subject_other: '[OpenStreetMap] %{commenter} å°±æ\82¨æ\84\9fè\88\88趣ç\9a\84è®\8aæ\9b´é\9b\86è©\95è«\96'
-        your_changeset: '%{commenter}於 %{time} 在您的變更集之一裡留下了評論'
-        your_changeset_html: '%{commenter}於 %{time} 在您的變更集之一裡留下了評論'
-        commented_changeset: '%{commenter}於 %{time} 在您監視的由%{changeset_author}所建立變更集裡留下了評論'
-        commented_changeset_html: '%{commenter}於 %{time} 在您監視的由%{changeset_author}所建立變更集裡留下了評論'
+        subject_own: '[OpenStreetMap] %{commenter} å°\8dä½ ç\9a\84è®\8aæ\9b´é\9b\86å\81\9aäº\86è©\95è«\96'
+        subject_other: '[OpenStreetMap] %{commenter} å°\8dä½ æ\84\9fè\88\88趣ç\9a\84è®\8aæ\9b´é\9b\86å\81\9aäº\86è©\95è«\96'
+        your_changeset: '%{commenter}於 %{time} 在你的變更集做了評論'
+        your_changeset_html: '%{commenter}於 %{time} 在你的變更集做了評論'
+        commented_changeset: '%{commenter}於 %{time} 在你監視、由%{changeset_author}建立的變更集做了評論'
+        commented_changeset_html: '%{commenter}於 %{time} 在你監視、由%{changeset_author}建立的變更集做了評論'
         partial_changeset_with_comment: 評論 "%{changeset_comment}"
         partial_changeset_with_comment_html: 評論 "%{changeset_comment}"
         partial_changeset_without_comment: 沒有評論
       details: 在 %{url} 回覆或瞭解更多有關於變更集的資訊。
       details_html: 在 %{url} 回覆或瞭解更多有關變更集的資訊。
-      unsubscribe: 可以在 %{url} 取消訂閱此變更集的更新內容。
-      unsubscribe_html: 可以在 %{url} 取消訂閱此變更集的更新內容。
+      unsubscribe: 可以在 %{url} 取消訂閱此變更集的更新內容。
+      unsubscribe_html: 可以在 %{url} 取消訂閱此變更集的更新內容。
   confirmations:
     confirm:
-      heading: 請檢查您的電子郵件!
-      introduction_1: æ\88\91å\80\91å¯\84給æ\82¨一封確認電子郵件。
+      heading: 檢查你的電子郵件!
+      introduction_1: æ\88\91å\80\91å·²ç¶\93å¯\84給你一封確認電子郵件。
       introduction_2: 按電子郵件中的連結以確認你的帳號,然後你就可以開始繪製地圖。
-      press confirm button: 按下確認按鈕以開啟的帳號。
+      press confirm button: 按下確認按鈕以開啟的帳號。
       button: 確認
-      success: 已確認您的帳號,感謝您的註冊!
+      success: 已確認你的帳號,感謝你的註冊!
       already active: 該帳號已經確認。
       unknown token: 確認碼已經過期或不存在。
-      resend_html: 如果要我們重新發送確認郵件,%{reconfirm_link}。
+      resend_html: 如果要我們重新發送確認郵件,%{reconfirm_link}。
       click_here: 在此點擊
     confirm_resend:
       failure: 找不到使用者 %{name}。
     confirm_email:
       heading: 確認電子郵件地址的變更
-      press confirm button: 按下確認按鈕以確認的新電子郵件地址。
+      press confirm button: 按下確認按鈕以確認的新電子郵件地址。
       button: 確認
-      success: 已確認變更的電子郵件地址!
-      failure: 電子郵件地址已使用此權杖確認過。
+      success: 已確認變更的電子郵件地址!
+      failure: 已有電子郵件地信箱使用此授權密鑰認證過。
       unknown_token: 確認碼已經過期或不存在。
     resend_success_flash:
-      confirmation_sent: 我們已發送新的確認通知到 %{email},一旦您確認您的帳號後,就能取得製圖
-      whitelist: 如果用來發送確認請求的信箱有反垃圾郵件系統,請確認有將 %{sender} 將入白名單,因為我們無法回覆任何確認請求。
+      confirmation_sent: 我們已發送新的確認通知到 %{email},一旦你確認你的帳號後,就能取得製圖權限
+      whitelist: 如果用來發送確認請求的信箱有反垃圾郵件系統,請確認有將 %{sender} 將入白名單,因為我們無法回覆任何確認請求。
   messages:
     inbox:
       title: 收件匣
@@ -1755,7 +1762,7 @@ zh-TW:
       old_messages:
         one: '%{count} 項舊訊息'
         other: '%{count} 項舊訊息'
-      no_messages_yet_html: 還沒有訊息。何不跟一些 %{people_mapping_nearby_link} 接觸看看?
+      no_messages_yet_html: 還沒有訊息。何不跟一些 %{people_mapping_nearby_link} 接觸看看?
       people_mapping_nearby: 在附近製圖的人
     messages_table:
       from: 寄件者
@@ -1775,7 +1782,7 @@ zh-TW:
       back_to_inbox: 回到收件匣
     create:
       message_sent: 已傳送訊息
-      limit_exceeded: 您最近寄出了大量的訊息。在嘗試寄出其他訊息之前請稍候。
+      limit_exceeded: 你最近寄出了大量的訊息,要再寄出訊息前請稍候
     no_such_message:
       title: 沒有這個訊息
       heading: 沒有這個訊息
@@ -1784,24 +1791,24 @@ zh-TW:
       title: 寄件匣
       actions: 操作
       messages:
-        one: 有 %{count} 項已寄訊息
-        other: 有 %{count} 項已寄訊息
-      no_sent_messages_html: 還沒有已寄訊息。何不跟一些 %{people_mapping_nearby_link} 接觸看看?
+        one: 有 %{count} 項已寄訊息
+        other: 有 %{count} 項已寄訊息
+      no_sent_messages_html: 還沒有已寄訊息。何不跟一些 %{people_mapping_nearby_link} 接觸看看?
       people_mapping_nearby: 附近製作地圖的使用者
     muted:
       title: 已忽視訊息
       messages:
         one: 1 條忽視訊息
-        other: 有 %{count} 條忽視訊息
+        other: 有 %{count} 條忽視訊息
     reply:
-      wrong_user: 您已經以「%{user}」的身份登入,但是您想要回覆的訊息並非寄給這個使用者。請以正確的使用者身份登入以回覆這個訊息。
+      wrong_user: 你已經以「%{user}」的身份登入,但是你想要回覆的訊息並非寄給這個使用者。請以正確的使用者身份登入以回覆這個訊息。
     show:
       title: 閱讀訊息
       reply_button: 回覆
       unread_button: 標記為未讀
       destroy_button: 刪除
       back: 返回
-      wrong_user: 您已經以「%{user}」的身份登入,但是您想要閱讀的訊息並非寄給那個使用者。請以正確的使用者身份登入以閱讀它。
+      wrong_user: 你已經以「%{user}」的身份登入,但是你想要閱讀的訊息並非寄給那個使用者。請以正確的使用者身份登入以閱讀它。
     sent_message_summary:
       destroy_button: 刪除
     heading:
@@ -1822,17 +1829,17 @@ zh-TW:
       heading: 忘記密碼?
       email address: 電子郵件地址
       new password button: 重設密碼
-      help_text: 輸入您的電子郵件地址來註冊,我們會將連結送至該地址,而您可以用它來重設密碼。
+      help_text: 輸入你的電子郵件地址來註冊,我們會將連結送至該地址,而你可以用它來重設密碼。
     create:
-      send_paranoid_instructions: 如果您的電子郵件地址存於我們的資料庫裡,您將在幾分鐘內收到密碼恢復連結的電郵
+      send_paranoid_instructions: 如果你的電子郵件地址存於我們的資料庫裡,你將在幾分鐘內收到有可恢復密碼連結的電子郵件
     edit:
       title: 重設密碼
       heading: 重設 %{user} 的密碼
       reset: 重設密碼
-      flash token bad: æ\89¾ä¸\8då\88°è©²æ¬\8aæ\9d\96,可能要檢查一下 URL?
+      flash token bad: æ\89¾ä¸\8då\88°è©²æ\8e\88æ¬\8aå¯\86é\91°,可能要檢查一下 URL?
     update:
-      flash changed: 的密碼已經變更。
-      flash token bad: æ\89¾ä¸\8då\88°è©²æ¬\8aæ\9d\96,可能要檢查一下 URL?
+      flash changed: 的密碼已經變更。
+      flash token bad: æ\89¾ä¸\8då\88°è©²æ\8e\88æ¬\8aå¯\86é\91°,可能要檢查一下 URL?
   preferences:
     show:
       title: 我的偏好設定
@@ -1857,14 +1864,14 @@ zh-TW:
         gravatar: 使用 Gravatar
         what_is_gravatar: 什麼是 Gravatar?
         disabled: Gravatar已停用。
-        enabled: 您的Gravatar顯示功能已啟用。
+        enabled: 你的 Gravatar 顯示功能已啟用。
       new image: 加入圖片
       keep image: 保持目前的圖片
       delete image: 移除目前的圖片
       replace image: 取代目前的圖片
       image size hint: ' (方形圖片至少 100x100 的效果最好)'
       home location: 家的位置
-      no home location: 尚未輸入家的位置。
+      no home location: 尚未輸入家的位置。
       update home location on click: 當我點選地圖時更新家的位置?
       show: 顯示
       delete: 刪除
@@ -1880,7 +1887,7 @@ zh-TW:
       email or username: 電子郵件地址或使用者名稱
       password: 密碼
       remember: 記住我
-      lost password link: 忘記您的密碼
+      lost password link: 忘記密碼了
       login_button: 登入
       register now: 立即註冊
       with external: 或者使用第三方服務登入
@@ -1891,8 +1898,8 @@ zh-TW:
       heading: 從 OpenStreetMap 登出
       logout_button: 登出
     suspended_flash:
-      suspended: 抱歉,由於可疑活動,的帳戶已被暫停。
-      contact_support_html: 如果您想商討此事,請聯繫 %{support_link}。
+      suspended: 抱歉,由於可疑活動,的帳戶已被暫停。
+      contact_support_html: 如果你想討論此事,請聯絡 %{support_link}。
       support: 支援
   shared:
     markdown_help:
@@ -1934,18 +1941,18 @@ zh-TW:
       community_driven_community_blogs: 社群部落格
       community_driven_osm_foundation: OSM 基金會
       open_data_title: 開放資料
-      open_data_1_html: OpenStreetMap 是%{open_data}的:您可以自由地使用作任何用途,前提是您須標明作者為 OpenStreetMap
-        及其貢獻者。若在我們的資料上作修改或以之透過某些方式衍生其他資料,則只可依相同授權條款散佈有關成果。詳情請參閱%{copyright_license_link}。
+      open_data_1_html: OpenStreetMap 是%{open_data}的:你可以自由地使用作任何用途,前提是必須標明作者為 OpenStreetMap
+        及其貢獻者。若在我們的資料上作修改或以之透過某些方式衍生其他資料,則只可依相同授權條款散佈有關成果。詳情請參閱%{copyright_license_link}。
       open_data_open_data: 開放資料
       open_data_copyright_license: 版權與授權條款頁面
       legal_title: 法律資訊
-      legal_1_1_html: 本站以及許多相關的服務正式由%{openstreetmap_foundation_link}(OSMF)代表社群所營運。所有使用的
+      legal_1_1_html: 本站以及許多相關的服務正式由%{openstreetmap_foundation_link} (OSMF) 代表社群所營運。所有使用的
         OSMF 運行服務皆符合我們的%{terms_of_use_link}、%{aup_link}、和%{privacy_policy_link}。
       legal_1_1_openstreetmap_foundation: OpenStreetMap 基金會
       legal_1_1_terms_of_use: 使用條款
       legal_1_1_aup: 可接受使用方針
       legal_1_1_privacy_policy: 隱私權政策
-      legal_2_1_html: 若有授權、版權、或其他法律上的問題,請%{contact_the_osmf_link}。
+      legal_2_1_html: 若有授權、版權、或其他法律上的問題,請%{contact_the_osmf_link}。
       legal_2_1_contact_the_osmf: 聯絡 OSMF
       legal_2_2_html: OpenStreetMap,查看地圖狀態的放大鏡模樣標誌是%{registered_trademarks_link}。
       legal_2_2_registered_trademarks: OSMF 的註冊商標
@@ -1958,28 +1965,29 @@ zh-TW:
         english_link: 英文原文
       native:
         title: 關於此頁
-        html: 您正在檢閱英文版本的版權頁。你可以返回這個網頁的 %{native_link},您亦可以停止閱讀版權並 %{mapping_link}。
+        html: 你正在檢閱英文版本的版權頁。你可以返回這個網頁的 %{native_link},也可以停止閱讀版權並 %{mapping_link}。
         native_link: 繁體中文版
         mapping_link: 開始製圖
       legal_babble:
-        introduction_1_html: OpenStreetMap%{registered_trademark_link}是%{open_data},透過%{osm_foundation_link}(OSMF)在%{odc_odbl_link}(ODbL)下授權。
+        introduction_1_html: OpenStreetMap%{registered_trademark_link}是%{open_data},透過%{osm_foundation_link}
+          (OSMF) 在%{odc_odbl_link}(ODbL)下授權。
         introduction_1_open_data: 開放資料
         introduction_1_odc_odbl: 開放資料共享開放資料庫授權
         introduction_1_osm_foundation: OpenStreetMap 基金會
-        introduction_2_html: 您可以自由地複製、散布、傳輸及修改我們的資料,前提是您須標明作者為 OpenStreetMap 及其貢獻者。若您在我們的資料上作變動或以此來建立其他資料,您只能依照相同授權條款來散佈成果。%{legal_code_link}有詳述您的權責。
+        introduction_2_html: 你可以自由複製、散布、傳輸及修改我們的資料,前提是必須標明作者為 OpenStreetMap 及其貢獻者。若在我們的資料上作變動或以此來建立其他資料,你只能依照相同授權條款來散佈成果。%{legal_code_link}有詳述你的權責。
         introduction_2_legal_code: 法律條款
         introduction_3_html: 我們的文件是依據 %{creative_commons_link} 授權條款(CC BY-SA 2.0)獲得許可。
         introduction_3_creative_commons: 創用 CC 姓名標示-相同方式分享
         introduction_3_creative_commons_url: https://creativecommons.org/licenses/by-sa/2.0/deed.zh_TW
         credit_title_html: 如何標明作者是 OpenStreetMap
-        credit_1_html: 當您使用 OpenStreetMap 的資料,您會被要求遵循兩件事:
+        credit_1_html: 當你使用 OpenStreetMap 的資料,你會被要求遵循兩件事:
         credit_2_1: 透過顯示我們的版權聲明為 OpenStreetMap 提供屬名。
         credit_2_2: 明確資料在開放資料共享開放資料庫授權下可用。
-        credit_3_html: 對於版權聲明的顯示,我們會依據您如何使用我們的資料,而有不同的要求。例如,不同的規則要如何顯示版權聲明,具體取決於您是否有建立可瀏覽的地圖、列印的地圖、或靜態圖片。完整的詳細資訊要求可以在%{attribution_guidelines_link}上查看。
+        credit_3_html: 對於版權聲明的顯示,我們會依據你如何使用我們的資料,而有不同的要求。例如:不同的規則要如何顯示版權聲明,具體取決於你是否有建立可瀏覽的地圖、列印的地圖、或靜態圖片。完整的詳細資訊要求可以在%{attribution_guidelines_link}上查看。
         credit_3_attribution_guidelines: 姓名標示指南
         credit_4_1_html: |-
-          請明確表示資料在開放資料庫授權條款下可用,可以連結到%{this_copyright_page_link}。
-          相對地,如果您以資料表來分發 OSM,您可以命名並直接連結到授權條款。在一些無法作出連結的媒體(例如印刷品),我們建議您引導您的讀者到 openstreetmap.org(像是註明「OpenStreetMap」的完整網址)以及 opendatacommons.org。
+          請明確表示資料在開放資料庫授權條款下可用,可以連結到%{this_copyright_page_link}。
+          相對地,如果你以資料表來分發 OSM,你可以命名並直接連結到授權條款。在一些無法作出連結的媒體 (例如印刷品),我們建議引導你的讀者到 openstreetmap.org (像是註明「OpenStreetMap」的完整網址) 以及 opendatacommons.org。
           在此範例中,版權相關聲明會出現在地圖的角落處。
         credit_4_1_this_copyright_page: 此版權頁面
         attribution_example:
@@ -1996,8 +2004,8 @@ zh-TW:
         more_2_1_nominatim_usage_policy: 提名使用方針
         contributors_title_html: 我們的貢獻者
         contributors_intro_html: 我們的貢獻者為成千上萬的人。我們也收納了從國家測繪機構及其他來源等取得的開放版權資料,其中包括:
-        contributors_at_credit_html: '%{austria}:包含來自%{stadt_wien_link}(依據%{cc_by_link})、%{land_vorarlberg_link}、與
-          Land Tirol(依據%{cc_by_at_with_amendments_link})的資料。'
+        contributors_at_credit_html: '%{austria}:包含來自%{stadt_wien_link} (依據%{cc_by_link})、%{land_vorarlberg_link}、與
+          Land Tirol (依據%{cc_by_at_with_amendments_link}) 的資料。'
         contributors_at_austria: 奧地利
         contributors_at_stadt_wien: 維也納
         contributors_at_cc_by: 創用 CC 姓名標示
@@ -2009,12 +2017,12 @@ zh-TW:
         contributors_au_geoscape_australia: Geoscape Australia
         contributors_au_cc_licence: 創用 CC 姓名標示 4.0 國際授權條款(CC BY 4.0)
         contributors_au_cc_licence_url: https://creativecommons.org/licenses/by/4.0/deed.zh_TW
-        contributors_ca_credit_html: '%{canada}:包含來自 GeoBase&reg;、GeoGratis(&copy;加拿大自然資源處)、CanVec(&copy;加拿大自然資源處)、和
-          StatCan(地理部,加拿大統計局)的資料。'
+        contributors_ca_credit_html: '%{canada}:包含來自 GeoBase&reg;、GeoGratis (&copy;加拿大自然資源處)、CanVec
+          (&copy;加拿大自然資源處)、和 StatCan (地理部,加拿大統計局) 的資料。'
         contributors_ca_canada: 加拿大
         contributors_cz_credit_html: '%{czechia}:包含來自土地測量局與依據%{cc_licence_link}許可的地籍資料'
         contributors_cz_czechia: 捷克
-        contributors_cz_cc_licence: 創用 CC 姓名標示 4.0 國際授權條款(CC BY 4.0)
+        contributors_cz_cc_licence: 創用 CC 姓名標示 4.0 國際授權條款 (CC BY 4.0)
         contributors_cz_cc_licence_url: https://creativecommons.org/licenses/by/4.0/deed.zh-hant
         contributors_fi_credit_html: '%{finland}:包含來自芬蘭測量局地形資料庫與其他資料集的資料,依據%{nlsfi_license_link}授權。'
         contributors_fi_finland: 芬蘭
@@ -2027,7 +2035,7 @@ zh-TW:
         contributors_hr_croatia: 克羅埃西亞
         contributors_hr_dgu: 克羅埃西亞國家大地測量局
         contributors_hr_open_data_portal: 國家開放資料入口網站
-        contributors_nl_credit_html: '%{netherlands}:包含 &copy; AND 資料,2007(%{and_link})'
+        contributors_nl_credit_html: '%{netherlands}:包含 &copy; AND 資料,2007 (%{and_link})'
         contributors_nl_netherlands: 荷蘭
         contributors_nz_credit_html: '%{new_zealand}:包含來自 %{linz_data_service_link}與基於%{cc_by_link}
           的重複使用授權條款。'
@@ -2061,26 +2069,26 @@ zh-TW:
         infringement_title_html: 侵犯版權
         infringement_1_html: OSM 的貢獻者會被提醒,絕不要在沒有版權所有人的明確淮許下,加入來自任何有版權的來源的資料 (如 Google
           地圖或印刷地圖)。
-        infringement_2_1_html: 如果認為有受版權保護的素材被不恰當地加到 OpenStreetMap 資料庫或本網站,請參考我們的%{takedown_procedure_link},或直接在我們的%{online_filing_page_link}反應。
+        infringement_2_1_html: 如果認為有受版權保護的素材被不恰當地加到 OpenStreetMap 資料庫或本網站,請參考我們的%{takedown_procedure_link},或直接在我們的%{online_filing_page_link}反應。
         infringement_2_1_takedown_procedure: 侵權處理程序
         infringement_2_1_online_filing_page: 線上申請頁面
         trademarks_title: 商標
         trademarks_1_1_html: OpenStreetMap、網站上的放大鏡標誌,和 State of the Map 是 OpenStreetMap
-          基金會的註冊商標。如果對商標的使用有任何疑問,請參閱我們的%{trademark_policy_link}。
+          基金會的註冊商標。如果對商標的使用有任何疑問,請參閱我們的%{trademark_policy_link}。
         trademarks_1_1_trademark_policy: 商標方針
     index:
-      js_1: 使用不支援 JavaScript 的瀏覽器,或者停用了 JavaScript。
+      js_1: 使用不支援 JavaScript 的瀏覽器,或者停用了 JavaScript。
       js_2: OpenStreetMap 使用 JavaScript 讓地圖更平順。
       license:
         copyright: 版權所有,由 OpenStreetMap 及貢獻者根據開放的授權協議提供
       remote_failed: 編輯失敗 - 請確定已載入 JOSM 或 Merkaartor 並開啟遠端控制選項
     edit:
-      not_public: 您尚未將您的編輯設為公開。
-      not_public_description_html: 在您這麼做之前將無法再編輯地圖。您可以在您的 %{user_page} 將自己的編輯設定為公開。
+      not_public: 你尚未將你的編輯設為公開。
+      not_public_description_html: 在你這麼做之前將無法再編輯地圖,可以在你的 %{user_page} 將自己的編輯設定為公開。
       user_page_link: 使用者頁面
       anon_edits_link_text: 瞭解為什麼這很重要。
       id_not_configured: iD 尚未設定
-      no_iframe_support: 的瀏覽器不支援 HTML 嵌入式框架,這是這項功能所必要的。
+      no_iframe_support: 的瀏覽器不支援 HTML 嵌入式框架,這是這項功能所必要的。
     export:
       title: 匯出
       manually_select: 手動選擇不同的區域
@@ -2115,10 +2123,10 @@ zh-TW:
         add_a_note:
           instructions_1_html: |-
             只需點選%{note_icon}或地圖上顯示的同一圖示,
-            這會在地圖上加入一個標記,您可以拖動它,並新增您的註記,然後點選儲存,其他製圖者會作出查證。
+            這會在地圖上加入一個標記,你可以拖動它,並新增你的註記,然後點選儲存,其他製圖者會作出查證。
       other_concerns:
         title: 其他問題
-        concerns_html: 如果對我們的資料使用方面或內容有所疑慮,請參考我們的%{copyright_link}來了解更多法律資訊,或是聯繫相應的%{working_group_link}。
+        concerns_html: 如果對我們的資料使用方面或內容有所疑慮,請參考我們的%{copyright_link}來了解更多法律資訊,或是聯繫相應的%{working_group_link}。
         copyright: 版權頁面
         working_group: OSMF 工作小組
     help:
@@ -2146,16 +2154,16 @@ zh-TW:
         description: 協助公司與組織改用 OpenStreetMap 為基礎的地圖與相關服務。
       welcomemat:
         title: 對於組織
-        description: 想要以組織來對 OpenStreetMap 製作計劃嗎?請在 Welcome Mat 查找所需要的事項。
+        description: 想要以組織來對 OpenStreetMap 製作計劃嗎?請在 Welcome Mat 查找所需要的事項。
       wiki:
         title: 開放街圖 Wiki
         description: 瀏覽 wiki,取得詳盡的開放街圖文件。
     potlatch:
-      removed: 您預設的開放街圖編輯器是設定成 Potlatch。因為 Adobe Flash Player 已終止維護,Potlatch 已不在網路瀏覽器上可用。
-      desktop_application_html: 仍然可以透過 %{download_link} 使用 Potlatch。
+      removed: 你預設的開放街圖編輯器是設定為 Potlatch。但因為 Adobe Flash Player 已終止維護,Potlatch 已不能在網路瀏覽器上使用。
+      desktop_application_html: 仍然可以透過 %{download_link} 使用 Potlatch。
       download: 下載適用於 Mac 和 Windows 的桌面應用程式
-      id_editor_html: 除此之外,您可以設定您的預設編輯器成 iD,這可以和先前的 Potlatch 一樣在您的網路瀏覽器上運作。%{change_preferences_link}。
-      change_preferences: 在此更改的偏好設定
+      id_editor_html: 除此之外,你可以設定預設編輯器為 iD,這可以和之前的 Potlatch 一樣在你的網路瀏覽器上運作。%{change_preferences_link}。
+      change_preferences: 在此更改的偏好設定
     any_questions:
       title: 有任何問題嗎?
       paragraph_1_html: |-
@@ -2181,18 +2189,18 @@ zh-TW:
         entry:
           motorway: 高速公路
           main_road: 主要幹道
-          trunk: 主要幹
-          primary: 一級道路
-          secondary: 二級道路
-          unclassified: 無編制道路
+          trunk: 快速公
+          primary: 省道
+          secondary: 縣道
+          unclassified: 未分級道路
           pedestrian: 人行道
           track: 產業道路
           bridleway: 馬道
           cycleway: 自行車道
           cycleway_national: 國家自行車道
-          cycleway_regional: å\8d\80å\9f\9f自行車道
-          cycleway_local: 地自行車道
-          cycleway_mtb: 登山車路
+          cycleway_regional: å\9c°å\8d\80自行車道
+          cycleway_local: 地自行車道
+          cycleway_mtb: 登山車路
           footway: 步道
           rail: 鐵路
           train: 列車
@@ -2203,7 +2211,7 @@ zh-TW:
           trolleybus: 無軌電車
           bus: 公車
           cable_car: 大型纜車
-          chair_lift: å\8d\87é\99\8då\90\8aæ¤\85
+          chair_lift: å\90\8aæ¤\85å¼\8fç´¢é\81\93
           runway: 機場跑道
           taxiway: 滑行道
           apron: 機場停機坪
@@ -2212,8 +2220,8 @@ zh-TW:
           city: 城市
           orchard: 果園
           vineyard: 葡萄園
-          forest: 
-          wood: 
+          forest: 人工
+          wood: 自然
           farmland: 農地
           grass: 草坪
           meadow: 牧草地
@@ -2222,29 +2230,29 @@ zh-TW:
           golf: 高爾夫球場
           park: 公園
           common: 共有地
-          built_up: 組成面積
+          built_up: 建成區
           resident: 住宅區
-          retail: 商店
+          retail: 零售商
           industrial: 工業區
           commercial: 商業區
           heathland: 石楠荒地
           scrubland: 灌木叢林地
           lake: 湖泊
-          reservoir: 水庫
+          reservoir: 水庫/大型蓄水池
           intermittent_water: 間歇性水體
           glacier: 冰河
-          reef: 礁
+          reef: 
           wetland: 濕地
           farm: 農田
-          brownfield: 低污染再利用地
+          brownfield: 棕色地 (受污染放置待恢復重開發地)
           cemetery: 公墓
           allotments: 社區農園
-          pitch: 運動場
+          pitch: 運動場
           centre: 運動中心
           beach: 海灘
-          reserve: è\87ªç\84¶ä¿\9dè­·å\8d\80
+          reserve: è\87ªç\84¶ä¿\9dè\82²
           military: 軍事區
-          school: 學校;大學
+          school: 學校
           university: 大學
           hospital: 醫院
           building: 重要建築
@@ -2255,8 +2263,8 @@ zh-TW:
           bridge: 黑線邊框 = 橋樑
           private: 私人進出
           destination: 目的地進出
-          construction: 建造中道路
-          bus_stop: 公車站
+          construction: 興建中道路
+          bus_stop: 公車站
           stop: 停車站
           bicycle_shop: 自行車店
           bicycle_rental: 自行車出租
@@ -2265,7 +2273,7 @@ zh-TW:
           toilets: 廁所
     welcome:
       title: 歡迎!
-      introduction: 歡迎來到 OpenStreetMap,自由和可編輯的世界地圖。您目前已經登入,可以開始繪製地圖。這裡有一份您須知道最重要事項的快速指南。
+      introduction: 歡迎來到 OpenStreetMap,自由和可編輯的世界地圖。你目前已經登入,可以開始繪製地圖。這裡有一份你必須知道的最重要事項的快速指南。
       whats_on_the_map:
         title: 地圖上有什麼
         on_the_map_html: |-
@@ -2290,7 +2298,7 @@ zh-TW:
       rules:
         title: 規則!
         para_1_html: |-
-          OpenStreetMap 幾乎沒有正式規則,但我們希望所有參與者都能與社群合作與溝通!。如果正在考慮
+          OpenStreetMap 幾乎沒有正式規則,但我們希望所有參與者都能與社群合作與溝通!。如果正在考慮
           除手動編輯之外的任何活動,請閱讀並遵循
           %{imports_link} 和 %{automated_edits_link}指南。
         imports: 匯入
@@ -2336,9 +2344,9 @@ zh-TW:
       help_url: https://wiki.openstreetmap.org/wiki/Upload
     create:
       upload_trace: 上傳 GPS 軌跡
-      trace_uploaded: 您的 GPX 檔案已經上傳並且在等候進入資料庫中。這通常不會超過半小時,完成時會以電子郵件通知您
+      trace_uploaded: 你的 GPX 檔案已經上傳並且在等候進入資料庫中。這通常不會超過半小時,完成時會以電子郵件通知
       upload_failed: 很抱歉,GPX 上傳失敗。已向管理員警告此錯誤,請再重試
-      traces_waiting: 有 %{count} 個軌跡等待上傳。請先等待先前的軌跡處理完後,再來繼續上傳其他軌跡,以免影響其他使用者的排程。
+      traces_waiting: 有 %{count} 個軌跡等待上傳。請先等待先前的軌跡處理完後,再來繼續上傳其他軌跡,以免影響其他使用者的排程。
     edit:
       cancel: 取消
       title: 編輯軌跡 %{name}
@@ -2421,15 +2429,15 @@ zh-TW:
   application:
     basic_auth_disabled: HTTP 基本認證已停用:%{link}
     oauth_10a_disabled: OAuth 1.0 與 1.0a 已停用:%{link}
-    permission_denied: 沒有權限來存取該操作。
+    permission_denied: 沒有權限來存取該操作。
     require_cookies:
-      cookies_needed: 您似乎已停用 cookies - 請在瀏覽器中開啟 cookies,然後繼續。
+      cookies_needed: 你似乎已停用 cookies - 請在瀏覽器中開啟 cookies 後再繼續。
     require_admin:
-      not_an_admin: 您需要是一個管理員才可執行該動作。
+      not_an_admin: 你必須是管理員才可執行該動作。
     setup_user_auth:
-      blocked_zero_hour: 您在OpenStreetMap網站有一個緊急訊息。在您儲存您的編輯內容前請先閱讀該訊息。
-      blocked: 已經被封鎖使用 API。請登入網頁介面以瞭解更多資訊。
-      need_to_see_terms: 我們已暫時中止您使用 API 的權限,請登入網頁介面查閱貢獻者條款,您不需要同意有關條款,但必須查閱它們。
+      blocked_zero_hour: 你在 OpenStreetMap 網站有一個緊急訊息。在儲存你的編輯內容前請先閱讀該訊息。
+      blocked: 已經被封鎖使用 API。請登入網頁介面以瞭解更多資訊。
+      need_to_see_terms: 我們已暫時中止你使用 API 的權限,請登入網頁介面查閱貢獻者條款,你不需要同意有關條款,但必須查閱它們。
     settings_menu:
       account_settings: 帳號設定
       oauth1_settings: OAuth 1 設定
@@ -2459,29 +2467,29 @@ zh-TW:
         alt: 維基百科標誌
   oauth:
     authorize:
-      title: 授權使用的帳號
-      request_access_html: 應用程式 %{app_name} 要求使用您的帳號,%{user}。請確定您要讓此應用程式使用下列功能。您可以依自己喜好,選擇多少項功能。
+      title: 授權使用的帳號
+      request_access_html: 應用程式 %{app_name} 要求使用你的帳號,%{user}。請確定你要讓此應用程式使用下列功能。你可以依自己喜好,選擇多少項功能。
       allow_to: 允許用戶端應用程式:
-      allow_read_prefs: 讀取的使用者偏好設定。
-      allow_write_prefs: 修改的使用者偏好設定。
+      allow_read_prefs: 讀取的使用者偏好設定。
+      allow_write_prefs: 修改的使用者偏好設定。
       allow_write_diary: 建立日記、評論和加入好友。
       allow_write_api: 修改地圖。
-      allow_read_gpx: 讀取的私人 GPS 軌跡。
+      allow_read_gpx: 讀取的私人 GPS 軌跡。
       allow_write_gpx: 上傳 GPS 軌跡。
       allow_write_notes: 修改註記。
       grant_access: 授權存取
     authorize_success:
       title: 允許授權請求
-      allowed_html: 您已授權應用程式 %{app_name} 使用您的帳號。
+      allowed_html: 你已授權應用程式 %{app_name} 使用你的帳號。
       verification: 驗證碼是 %{code}。
     authorize_failure:
       title: 授權請求失敗
-      denied: 您已拒絕應用程式 %{app_name} 使用您的帳號。
-      invalid: 授權權杖無效。
+      denied: 你已拒絕應用程式 %{app_name} 使用你的帳號。
+      invalid: 認證授權密鑰無效。
     revoke:
-      flash: 已經撤銷 %{application} 的授權密鑰。
+      flash: 已經撤銷 %{application} 的授權密鑰。
     permissions:
-      missing: 尚未允許應用程式來訪問此設施
+      missing: 尚未允許應用程式來訪問此設施
     scopes:
       openid: 使用 OpenStreetMap 登入
       read_prefs: 讀取使用者偏好設定
@@ -2493,6 +2501,8 @@ zh-TW:
       write_notes: 修改註記
       write_redactions: 編寫地圖資料
       read_email: 讀取使用者電子郵件位址
+      consume_messages: 讀取、更新狀態、與刪除使用者訊息
+      send_messages: 傳送私人訊息給其他使用者
       skip_authorization: 自動核准申請
     for_roles:
       moderator: 此權限用於僅可由仲裁員執行的操作
@@ -2501,31 +2511,31 @@ zh-TW:
       title: 註冊新的應用程式
       disabled: 已停用 OAuth 1 應用程式的註冊
     edit:
-      title: 編輯的應用程式
+      title: 編輯的應用程式
     show:
       title: '%{app_name} 的 OAuth 詳細資料'
       key: 消費者金鑰:
       secret: 消費者祕密金鑰:
-      url: è¦\81æ±\82æ¬\8aæ\9d\96 URL:
-      access_url: 存取記號 URL:
+      url: è¦\81æ±\82æ\8e\88æ¬\8aå¯\86é\91° URL:
+      access_url: 連接授權密鑰 URL:
       authorize_url: 授權 URL:
       support_notice: 我們支援 HMAC-SHA1 (建議) 和 RSA-SHA1 署名。
       edit: 編輯詳細資料
       delete: 刪除客戶端
-      confirm: 確定嗎?
+      confirm: 確定嗎?
       requests: 向使用者要求下列權限:
     index:
       title: 我的 OAuth 詳細資料
       my_tokens: 我授權的應用程式
-      list_tokens: ä¸\8bå\88\97æ¬\8aæ\9d\96已核ç\99¼çµ¦æ\82¨名下的應用程式:
+      list_tokens: ä¸\8bå\88\97æ\8e\88æ¬\8aå¯\86é\91°å·²æ ¸ç\99¼çµ¦ä½ 名下的應用程式:
       application: 應用程式名稱
       issued_at: 已發於
       revoke: 撤銷!
       my_apps: 我的用戶端應用程式
-      no_apps_html: 您是否有想要註冊以使用於 %{oauth} 標準的應用程式?您必須先註冊您的網頁應用程式,才能對這個服務進行 OAuth 要求。
+      no_apps_html: 你是否有想要註冊以使用於 %{oauth} 標準的應用程式?你必須先註冊你的網頁應用程式,才能對這個服務進行 OAuth 要求。
       oauth: OAuth
-      registered_apps: 已經註冊下列用戶端應用程式:
-      register_new: 註冊的應用程式
+      registered_apps: 已經註冊下列用戶端應用程式:
+      register_new: 註冊的應用程式
     form:
       requests: 向使用者要求下列權限:
     not_found:
@@ -2539,8 +2549,8 @@ zh-TW:
   oauth2_applications:
     index:
       title: 我的客戶端應用程式
-      no_applications_html: 您是否有想要註冊以使用於 %{oauth2} 標準的應用程式?您必須先註冊您的網頁應用程式,才能對這個服務進行
-        OAuth 要求。
+      no_applications_html: 你是否要跟我們註冊使用 %{oauth2} 標準的應用程式?你必須先註冊該應用程式,才能對這個服務進行 OAuth
+        要求。
       new: 註冊新的應用程式
       name: 名稱
       permissions: 權限
@@ -2551,7 +2561,7 @@ zh-TW:
     new:
       title: 註冊新的應用程式
     edit:
-      title: 編輯的應用程式
+      title: 編輯的應用程式
     show:
       edit: 編輯
       delete: 刪除
@@ -2566,7 +2576,7 @@ zh-TW:
   oauth2_authorizations:
     new:
       title: 需要授權
-      introduction: 要授權 %{application} 能使用以下權限來存取的帳號嗎?
+      introduction: 要授權 %{application} 能使用以下權限來存取的帳號嗎?
       authorize: 授權
       deny: 拒絕
     error:
@@ -2579,7 +2589,7 @@ zh-TW:
       application: 應用程式
       permissions: 權限
       last_authorized: 最後授權
-      no_applications_html: 未授權任何 %{oauth2} 應用程式。
+      no_applications_html: 未授權任何 %{oauth2} 應用程式。
     application:
       revoke: 撤銷存取權限
       confirm_revoke: 撤銷此應用程式的撤銷存取權限?
@@ -2588,7 +2598,7 @@ zh-TW:
       title: 註冊
       tab_title: 註冊
       signup_to_authorize_html: 註冊 OpenStreetMap 以存取 %{client_app_name}。
-      no_auto_account_create: 很不幸的我們現在無法自動為您建立帳號。
+      no_auto_account_create: 很不幸的,我們現在無法自動為你建立帳號。
       please_contact_support_html: 請聯繫 %{support_link} 來安排建立帳號 - 我們會盡快處理這份請求。
       support: 支援
       about:
@@ -2596,10 +2606,10 @@ zh-TW:
         paragraph_1: 不像其他地圖,開放街圖是完全由像你我這類創建,而且任何都能修正、更新、下載與使用。
         paragraph_2: 註冊並開始貢獻。
         welcome: 歡迎來到 OpenStreetMap
-      duplicate_social_email: 若您已有 OpenStreetMap 帳號,並希望使用第三方身份提供者,請使用您的密碼登入並修改您帳號的設定。
-      display name description: 您公開顯示的使用者名稱。您可以稍後在偏好設定中改變它。
+      duplicate_social_email: 若你已有 OpenStreetMap 帳號,並希望使用第三方身份提供者,請使用你的密碼登入並修改帳號的設定。
+      display name description: 你公開顯示的使用者名稱,之後可以在偏好設定中改變它。
       by_signing_up:
-        html: 註冊即表示同意我們的 %{tou_link}、%{privacy_policy_link} 與 %{contributor_terms_link}。
+        html: 註冊即表示同意我們的 %{tou_link}、%{privacy_policy_link} 與 %{contributor_terms_link}。
         privacy_policy: 隱私權政策
         privacy_policy_title: OSMF 隱私權政策包含電子郵件地址部份
         contributor_terms_url: https://wiki.osmfoundation.org/wiki/Licence/Contributor_Terms
@@ -2607,11 +2617,11 @@ zh-TW:
       tou: 使用條款
       external auth: 第三方身份認證
       continue: 註冊
-      terms accepted: 感謝接受新的貢獻條款!
+      terms accepted: 感謝接受新的貢獻條款!
       email_help:
         privacy_policy: 隱私權政策
         privacy_policy_title: OSMF 隱私權政策包含電子郵件地址部份
-        html: 的地址不會公開顯示,請參閱我們的%{privacy_policy_link}來了解更多資訊。
+        html: 的地址不會公開顯示,請參閱我們的%{privacy_policy_link}來了解更多資訊。
       consider_pd_html: 我認為我的貢獻屬於 %{consider_pd_link}。
       consider_pd: 公有領域
       consider_pd_url: https://wiki.osmfoundation.org/wiki/Licence_and_Legal_FAQ/Why_would_I_want_my_contributions_to_be_public_domain
@@ -2622,7 +2632,7 @@ zh-TW:
       heading: 條款
       heading_ct: 貢獻者條款
       read and accept with tou: 請閱讀貢獻者協議與使用條款,勾選兩項方框後點擊繼續按鈕。
-      contributor_terms_explain: 此協議適用於現有與往後貢獻的條款。
+      contributor_terms_explain: 此協議適用於現有與往後貢獻的條款。
       read_ct: 我已閱讀過並同意以上的貢獻者條款
       tou_explain_html: 這些%{tou_link}適用於網站方面的使用,與其它由 OSMF 提供的基礎內容。請在連結上點擊,閱讀並同意該文字。
       read_tou: 我已經閱讀過並同意使用條款
@@ -2637,7 +2647,7 @@ zh-TW:
       legale_select: 請選擇您的居住地:
       legale_names:
         france: 法國
-        italy: 大利
+        italy: 大利
         rest_of_world: 世界其他地區
     terms_declined_flash:
       terms_declined_html: 我們很遺憾你已決定不接受新的貢獻者條款。有關詳細資訊,請參閱 %{terms_declined_link}。
@@ -2645,7 +2655,7 @@ zh-TW:
     no_such_user:
       title: 沒有這個使用者
       heading: 使用者 %{user} 不存在
-      body: 抱歉,沒有名為 %{user} 的使用者。請檢查您的拼字,或者可能是您按到錯誤的連結。
+      body: 抱歉,沒有名為 %{user} 的使用者。請檢查你的拼字,或者可能是你按到錯誤的連結。
       deleted: 已刪除賬號
     show:
       my diary: 我的日記
@@ -2708,7 +2718,7 @@ zh-TW:
       confirm: 確認
       report: 回報此使用者
     go_public:
-      flash success: 現在您所有的編輯都是公開的,而您已獲准編輯。
+      flash success: 現在你所有的編輯都是公開的,而你已獲准編輯。
     index:
       title: 使用者
       heading: 使用者
@@ -2726,8 +2736,8 @@ zh-TW:
       title: 帳號已暫停
       heading: 帳號已暫停
       support: 支援
-      automatically_suspended: 很抱歉,出自於可疑活動緣故,的帳號已被自動暫時停用。
-      contact_support_html: 管理員將會很快審查此決定,若您想討論這個問題,您可以聯繫 %{support_link}。
+      automatically_suspended: 很抱歉,出自於可疑活動緣故,的帳號已被自動暫時停用。
+      contact_support_html: 管理員將會很快審查此決定,若你想討論這個問題,可以聯繫 %{support_link}。
     auth_failure:
       connection_failed: 連線至認證供應者失敗
       invalid_credentials: 無效的認證憑證
@@ -2736,9 +2746,9 @@ zh-TW:
       invalid_scope: 無效範圍
       unknown_error: 驗證失敗
     auth_association:
-      heading: 您的ID尚未與OpenStreetMap帳號關聯。
-      option_1: 如果您新來到OpenStreetMap,請使用下方表單建立一個帳號。
-      option_2: 如果您已擁有一個帳號,您可以用您的使用者名稱與密碼登入您的帳號,並在使用者設定中關連您的ID。
+      heading: 你的 ID 尚未與 OpenStreetMap 帳號關聯。
+      option_1: 如果你是新來到 OpenStreetMap,請使用下方表單建立一個帳號。
+      option_2: 如果你已擁有一個帳號,可以用你的使用者名稱與密碼登入你的帳號,並在使用者設定中關連你的 ID。
   user_role:
     filter:
       not_a_role: 字串 "%{role}" 不是有效的身份。
@@ -2748,13 +2758,13 @@ zh-TW:
     grant:
       title: 確認授與身份
       heading: 確認授與身份
-      are_you_sure: 確定要授予使用者 "%{name}"  "%{role}" 的身份?
+      are_you_sure: 確定要授予使用者 "%{name}"  "%{role}" 的身份?
       confirm: 確認
       fail: 無法授予使用者 "%{name}"  "%{role}" 的身份。請檢查使用者和身份是否都正確。
     revoke:
       title: 確認撤銷身份
       heading: 確認撤銷身份
-      are_you_sure: 確定要撤銷使用者 "%{name}"  "%{role}" 的身份?
+      are_you_sure: 確定要撤銷使用者 "%{name}"  "%{role}" 的身份?
       confirm: 確認
       fail: 無法撤銷使用者 "%{name}"  "%{role}" 的身份。請檢查使用者和身份是否都正確。
   user_blocks:
@@ -2776,12 +2786,12 @@ zh-TW:
       show: 檢視這項封鎖
       back: 檢視所有的封鎖
     filter:
-      block_expired: 這項封鎖已經逾期並且不能被編輯。
       block_period: 封鎖期間必須是在下拉式選單中選填擇的其中一項數值。
     create:
       flash: 已建立對使用者 %{name} 的封鎖。
     update:
       only_creator_can_edit: 只有建立這項封鎖的仲裁員可作出編輯。
+      only_creator_or_revoker_can_edit: 只有建立或撤銷此封鎖的仲裁員可作出編輯。
       success: 封鎖已更新。
     index:
       title: 使用者封鎖
@@ -2799,7 +2809,7 @@ zh-TW:
       title: 正在撤銷對%{block_on}的封鎖
       heading_html: 正在撤銷對%{block_on}的所有封鎖
       empty: '%{name}沒有生效的封鎖。'
-      confirm: 確定要撤銷%{active_blocks}嗎?
+      confirm: 確定要撤銷%{active_blocks}嗎?
       active_blocks:
         one: '%{count} 個生效封鎖'
         other: '%{count} 個生效封鎖'
@@ -2843,7 +2853,7 @@ zh-TW:
       show: 顯示
       edit: 編輯
       revoke: 撤銷!
-      confirm: 確定嗎?
+      confirm: 確定嗎?
       reason: 封鎖的理由:
       revoker: 撤銷者:
       needs_view: 在還原這個封鎖之前,該使用者需要先登入。
@@ -2872,10 +2882,10 @@ zh-TW:
       title: 已忽視使用者
       my_muted_users: 我忽視的使用者
       you_have_muted_n_users:
-        one: 已忽視 1 名使用者
-        other: 已忽視 %{count} 名使用者
+        one: 已忽視 1 名使用者
+        other: 已忽視 %{count} 名使用者
       user_mute_explainer: 已忽視使用者的訊息會移至單獨的收件匣中,您將不會收到電子郵件通知。
-      user_mute_admins_and_moderators: 可以忽視管理員和仲裁員,但仍會收到他們的訊息通知。
+      user_mute_admins_and_moderators: 可以忽視管理員和仲裁員,但仍會收到他們的訊息通知。
       table:
         thead:
           muted_user: 已忽視使用者
@@ -2884,10 +2894,10 @@ zh-TW:
           unmute: 取消忽視
           send_message: 寄送訊息
     create:
-      notice: 已忽視%{name}。
+      notice: 已忽視%{name}。
       error: 無法忽視%{name}。%{full_message}。
     destroy:
-      notice: 取消了忽視%{name}。
+      notice: 取消了忽視%{name}。
       error: 無法忽視使用者。請再試一次。
   notes:
     index:
@@ -2925,17 +2935,17 @@ zh-TW:
       comment_and_resolve: 評論並解決
       comment: 評論
       log_in_to_comment: 登入來評論此註記
-      report_link_html: 如果此註記含有需要移除的敏感資訊,可以%{link}。
-      other_problems_resolve: 對於註記的所有其他問題,可以依據評論內容來自行處理。
+      report_link_html: 如果此註記含有需要移除的敏感資訊,可以%{link}。
+      other_problems_resolve: 對於註記的所有其他問題,可以依據評論內容來自行處理。
       other_problems_resolved: 對於其他類型回報,解決已經足夠了。
       disappear_date_html: 已解決的註記會在%{disappear_in}後從地圖中消失
     new:
       title: 新增註記
       intro: 發現錯誤或缺少些什麼東西嗎?請告訴其他地圖製作者以便於我們處理。將標記移動到正確的位置並輸入註記,以解釋問題。
-      anonymous_warning_html: 您尚未登入。若您想收到您的註記更新內容,請%{log_in}或%{sign_up}。
+      anonymous_warning_html: 你尚未登入。若想收到你的註記更新內容,請%{log_in}或%{sign_up}。
       anonymous_warning_log_in: 登入
       anonymous_warning_sign_up: 註冊
-      advice: 的註記已公開並可用於更新地圖,因此請不要輸入個人訊息,或是來自於具版權保護地圖的訊息以及目錄清單。
+      advice: 的註記已公開並可用於更新地圖,因此請不要輸入個人訊息,或是來自於具版權保護地圖的訊息以及目錄清單。
       add: 送出註記
   javascripts:
     close: 關閉
@@ -2951,14 +2961,14 @@ zh-TW:
       custom_dimensions: 設定自訂的尺寸
       format: 格式:
       scale: 比例:
-      image_dimensions: 圖片會顯示成 %{width} x %{height} 標準圖層
+      image_dimensions: 圖片會顯示成 %{width} x %{height} %{layer}圖層
       download: 下載
       short_url: 簡短 URL
       include_marker: 包括標記
       center_marker: 將標記設為地圖中心點
       paste_html: 貼上 HTML 以嵌入網站
       view_larger_map: 查看更大的地圖
-      only_standard_layer: 只有標準圖層能匯出成圖片
+      only_standard_layer: 只有標準圖層、自行車地圖、交通運輸圖層能匯出成圖片
     embed:
       report_problem: 回報問題
     key:
@@ -2972,11 +2982,11 @@ zh-TW:
       locate:
         title: 顯示我的位置
         metersPopup:
-          one: 您距離此地點在 %{count} 公尺內
-          other: 您距離此地點在 %{count} 公尺內
+          one: 你距離此地點不到 %{count} 公尺
+          other: 你距離此地點不到 %{count} 公尺
         feetPopup:
-          one: 您距離此地點在 %{count} 英尺內
-          other: 您距離此地點在 %{count} 英尺內
+          one: 你距離此地點不到 %{count} 英尺
+          other: 你距離此地點不到 %{count} 英尺
       base:
         standard: 標準
         cycle_map: 自行車地圖
@@ -3018,16 +3028,16 @@ zh-TW:
         fossgis_osrm_bike: 自行車(OSRM)
         fossgis_osrm_car: 開車 (OSRM)
         fossgis_osrm_foot: 步行(OSRM)
-        graphhopper_bicycle: 自行車(GraphHopper)
-        graphhopper_car: 汽車(GraphHopper)
-        graphhopper_foot: 徒步 (GraphHopper)
-        fossgis_valhalla_bicycle: è\85³è¸\8fè»\8a (ç\93¦ç\88¾å\93\88æ\8b\89)
-        fossgis_valhalla_car: 車 (瓦爾哈拉)
-        fossgis_valhalla_foot: 步行 (瓦爾哈拉)
+        graphhopper_bicycle: 自行車 (GraphHopper)
+        graphhopper_car: 開車 (GraphHopper)
+        graphhopper_foot: 步行 (GraphHopper)
+        fossgis_valhalla_bicycle: è\87ªè¡\8cè»\8a (Valhalla)
+        fossgis_valhalla_car: 開車 (Valhalla)
+        fossgis_valhalla_foot: 步行 (Valhalla)
       descend: 下降
       directions: 路線
       distance: 距離
-      distance_m: '%{distance} m'
+      distance_m: '%{distance} 公尺'
       distance_km: '%{distance}公里'
       errors:
         no_route: 查無兩個地點間的路徑。
@@ -3131,13 +3141,13 @@ zh-TW:
       user: 建立者:
       edit: 編輯此修訂
       destroy: 移除此修訂
-      confirm: 確定嗎?
+      confirm: 確定嗎?
     create:
       flash: 修訂已建立
     update:
       flash: 已儲存變更。
     destroy:
-      not_empty: 修訂尚未清空請在銷毀前清除所有此修訂的版本。
+      not_empty: 修訂尚未清空請在銷毀前清除所有此修訂的版本。
       flash: 修訂已銷毀。
       error: 銷毀此修訂時發生錯誤。
   validations:
index 12f6325ae3d78acce9469195f084a4776804e4c9..650818d6fc8f45cf0b1839f488ffdbc2cda0f2ba 100644 (file)
@@ -78,15 +78,26 @@ OpenStreetMap::Application.routes.draw do
       end
     end
 
+    resources :messages, :path => "user/messages", :constraints => { :id => /\d+/ }, :only => [:create, :show, :destroy], :controller => "messages", :as => :api_messages do
+      collection do
+        get "inbox"
+        get "outbox"
+      end
+    end
+
+    post "/user/messages/:id" => "messages#update", :as => :api_message_update
+
     post "gpx/create" => "traces#create"
     get "gpx/:id" => "traces#show", :as => :api_trace, :id => /\d+/
     put "gpx/:id" => "traces#update", :id => /\d+/
     delete "gpx/:id" => "traces#destroy", :id => /\d+/
     get "gpx/:id/details" => "traces#show", :id => /\d+/
     get "gpx/:id/data" => "traces#data", :as => :api_trace_data
+  end
 
+  namespace :api, :path => "api/0.6" do
     # Map notes API
-    resources :notes, :except => [:new, :edit, :update], :constraints => { :id => /\d+/ }, :controller => "notes", :as => :api_notes do
+    resources :notes, :except => [:new, :edit, :update], :id => /\d+/, :controller => "notes" do
       collection do
         get "search"
         get "feed", :defaults => { :format => "rss" }
@@ -99,7 +110,7 @@ OpenStreetMap::Application.routes.draw do
       end
     end
 
-    resources :user_blocks, :only => [:show], :constraints => { :id => /\d+/ }, :controller => "user_blocks", :as => :api_user_blocks
+    resources :user_blocks, :only => :show, :id => /\d+/, :controller => "user_blocks"
   end
 
   # Data browsing
index fa7207721c9dd28db5ce5c35281f60e7a20f3227..71df9ad3d7ef560eb732bbcf2467351b349209dd 100644 (file)
@@ -59,6 +59,10 @@ user_block_periods: [0, 1, 3, 6, 12, 24, 48, 96, 168, 336, 731, 4383, 8766, 8766
 user_account_deletion_delay: null
 # Rate limit for message sending
 max_messages_per_hour: 60
+# Default limit on the number of messages returned by inbox and outbox message api
+default_message_query_limit: 100
+# Maximum number of messages returned by inbox and outbox message api
+max_message_query_limit: 100
 # Rate limit for friending
 max_friends_per_hour: 60
 # Rate limit for changeset comments
index 88db38eb4bf914b8331655e134cbdf70b243c4ee..a8f49762112a739ccb351ff130dd71bc678ba6e5 100644 (file)
@@ -2,7 +2,7 @@ module Oauth
   SCOPES = %w[read_prefs write_prefs write_diary write_api read_gpx write_gpx write_notes].freeze
   PRIVILEGED_SCOPES = %w[read_email skip_authorization].freeze
   MODERATOR_SCOPES = %w[write_redactions].freeze
-  OAUTH2_SCOPES = %w[write_redactions openid].freeze
+  OAUTH2_SCOPES = %w[write_redactions consume_messages send_messages openid].freeze
 
   class Scope
     attr_reader :name
index f19d3d3a952ddd2c8240e2ea8da228c434523ffc..a439342f7743f9b1fb8682147f6562a9ff0750ab 100644 (file)
@@ -53,6 +53,10 @@ module RichText
       nil
     end
 
+    def image_alt
+      nil
+    end
+
     protected
 
     def simple_format(text)
@@ -92,9 +96,13 @@ module RichText
     end
 
     def image
-      return @image if defined? @image
+      @image_element = first_image_element(document.root) unless defined? @image_element
+      @image_element.attr["src"] if @image_element
+    end
 
-      @image = first_image_element(document.root)&.attr&.[]("src")
+    def image_alt
+      @image_element = first_image_element(document.root) unless defined? @image_element
+      @image_element.attr["alt"] if @image_element
     end
 
     private
@@ -104,13 +112,17 @@ module RichText
     end
 
     def first_image_element(element)
-      return element if element.type == :img
+      return element if image?(element) && element.attr["src"].present?
 
       element.children.find do |child|
         nested_image = first_image_element(child)
         break nested_image if nested_image
       end
     end
+
+    def image?(element)
+      element.type == :img || (element.type == :html_element && element.value == "img")
+    end
   end
 
   class Text < Base
index 10419c0f814b2e8b240cb80b3263b2f85857a7dd..bcfcaf74e4d809ad0a8aba72af5c0837f8af062d 100644 (file)
@@ -4,7 +4,7 @@ require "test_helper"
 
 class ChangesetCommentApiCapabilityTest < ActiveSupport::TestCase
   test "as a normal user with permissionless token" do
-    token = create(:access_token)
+    token = create(:oauth_access_token)
     capability = ApiCapability.new token
 
     [:create, :destroy, :restore].each do |action|
@@ -12,8 +12,8 @@ class ChangesetCommentApiCapabilityTest < ActiveSupport::TestCase
     end
   end
 
-  test "as a normal user with allow_write_api token" do
-    token = create(:access_token, :allow_write_api => true)
+  test "as a normal user with write_api token" do
+    token = create(:oauth_access_token, :scopes => %w[write_api])
     capability = ApiCapability.new token
 
     [:destroy, :restore].each do |action|
@@ -26,7 +26,7 @@ class ChangesetCommentApiCapabilityTest < ActiveSupport::TestCase
   end
 
   test "as a moderator with permissionless token" do
-    token = create(:access_token, :user => create(:moderator_user))
+    token = create(:oauth_access_token, :resource_owner_id => create(:moderator_user).id)
     capability = ApiCapability.new token
 
     [:create, :destroy, :restore].each do |action|
@@ -34,8 +34,8 @@ class ChangesetCommentApiCapabilityTest < ActiveSupport::TestCase
     end
   end
 
-  test "as a moderator with allow_write_api token" do
-    token = create(:access_token, :user => create(:moderator_user), :allow_write_api => true)
+  test "as a moderator with write_api token" do
+    token = create(:oauth_access_token, :resource_owner_id => create(:moderator_user).id, :scopes => %w[write_api])
     capability = ApiCapability.new token
 
     [:create, :destroy, :restore].each do |action|
@@ -46,7 +46,7 @@ end
 
 class NoteApiCapabilityTest < ActiveSupport::TestCase
   test "as a normal user with permissionless token" do
-    token = create(:access_token)
+    token = create(:oauth_access_token)
     capability = ApiCapability.new token
 
     [:create, :comment, :close, :reopen, :destroy].each do |action|
@@ -54,8 +54,8 @@ class NoteApiCapabilityTest < ActiveSupport::TestCase
     end
   end
 
-  test "as a normal user with allow_write_notes token" do
-    token = create(:access_token, :allow_write_notes => true)
+  test "as a normal user with write_notes token" do
+    token = create(:oauth_access_token, :scopes => %w[write_notes])
     capability = ApiCapability.new token
 
     [:destroy].each do |action|
@@ -68,7 +68,7 @@ class NoteApiCapabilityTest < ActiveSupport::TestCase
   end
 
   test "as a moderator with permissionless token" do
-    token = create(:access_token, :user => create(:moderator_user))
+    token = create(:oauth_access_token, :resource_owner_id => create(:moderator_user).id)
     capability = ApiCapability.new token
 
     [:destroy].each do |action|
@@ -76,8 +76,8 @@ class NoteApiCapabilityTest < ActiveSupport::TestCase
     end
   end
 
-  test "as a moderator with allow_write_notes token" do
-    token = create(:access_token, :user => create(:moderator_user), :allow_write_notes => true)
+  test "as a moderator with write_notes token" do
+    token = create(:oauth_access_token, :resource_owner_id => create(:moderator_user).id, :scopes => %w[write_notes])
     capability = ApiCapability.new token
 
     [:destroy].each do |action|
@@ -95,14 +95,14 @@ class UserApiCapabilityTest < ActiveSupport::TestCase
     end
 
     # A user with empty tokens
-    token = create(:access_token)
+    token = create(:oauth_access_token)
     capability = ApiCapability.new token
 
     [:index, :show, :update_all, :update, :destroy].each do |act|
       assert capability.cannot? act, UserPreference
     end
 
-    token = create(:access_token, :allow_read_prefs => true)
+    token = create(:oauth_access_token, :scopes => %w[read_prefs])
     capability = ApiCapability.new token
 
     [:update_all, :update, :destroy].each do |act|
@@ -113,7 +113,7 @@ class UserApiCapabilityTest < ActiveSupport::TestCase
       assert capability.can? act, UserPreference
     end
 
-    token = create(:access_token, :allow_write_prefs => true)
+    token = create(:oauth_access_token, :scopes => %w[write_prefs])
     capability = ApiCapability.new token
 
     [:index, :show].each do |act|
index e7d8ca2095134abfbfc7ae43585633da8d1d615b..f479b24b3cb99b3b9f68921fd772086f69bd4103 100644 (file)
@@ -46,7 +46,7 @@ module Api
       assert_difference "ChangesetComment.count", 1 do
         assert_no_difference "ActionMailer::Base.deliveries.size" do
           perform_enqueued_jobs do
-            post changeset_comment_path(:id => private_user_closed_changeset, :text => "This is a comment"), :headers => auth_header
+            post changeset_comment_path(private_user_closed_changeset, :text => "This is a comment"), :headers => auth_header
           end
         end
       end
@@ -61,7 +61,7 @@ module Api
       assert_difference "ChangesetComment.count", 1 do
         assert_difference "ActionMailer::Base.deliveries.size", 1 do
           perform_enqueued_jobs do
-            post changeset_comment_path(:id => changeset, :text => "This is a comment"), :headers => auth_header
+            post changeset_comment_path(changeset, :text => "This is a comment"), :headers => auth_header
           end
         end
       end
@@ -79,7 +79,7 @@ module Api
       assert_difference "ChangesetComment.count", 1 do
         assert_difference "ActionMailer::Base.deliveries.size", 2 do
           perform_enqueued_jobs do
-            post changeset_comment_path(:id => changeset, :text => "This is a comment"), :headers => auth_header
+            post changeset_comment_path(changeset, :text => "This is a comment"), :headers => auth_header
           end
         end
       end
@@ -102,32 +102,32 @@ module Api
     # create comment fail
     def test_create_comment_fail
       # unauthorized
-      post changeset_comment_path(:id => create(:changeset, :closed), :text => "This is a comment")
+      post changeset_comment_path(create(:changeset, :closed), :text => "This is a comment")
       assert_response :unauthorized
 
       auth_header = basic_authorization_header create(:user).email, "test"
 
       # bad changeset id
       assert_no_difference "ChangesetComment.count" do
-        post changeset_comment_path(:id => 999111, :text => "This is a comment"), :headers => auth_header
+        post changeset_comment_path(999111, :text => "This is a comment"), :headers => auth_header
       end
       assert_response :not_found
 
       # not closed changeset
       assert_no_difference "ChangesetComment.count" do
-        post changeset_comment_path(:id => create(:changeset), :text => "This is a comment"), :headers => auth_header
+        post changeset_comment_path(create(:changeset), :text => "This is a comment"), :headers => auth_header
       end
       assert_response :conflict
 
       # no text
       assert_no_difference "ChangesetComment.count" do
-        post changeset_comment_path(:id => create(:changeset, :closed)), :headers => auth_header
+        post changeset_comment_path(create(:changeset, :closed)), :headers => auth_header
       end
       assert_response :bad_request
 
       # empty text
       assert_no_difference "ChangesetComment.count" do
-        post changeset_comment_path(:id => create(:changeset, :closed), :text => ""), :headers => auth_header
+        post changeset_comment_path(create(:changeset, :closed), :text => ""), :headers => auth_header
       end
       assert_response :bad_request
     end
@@ -142,13 +142,13 @@ module Api
 
       assert_difference "ChangesetComment.count", Settings.initial_changeset_comments_per_hour do
         1.upto(Settings.initial_changeset_comments_per_hour) do |count|
-          post changeset_comment_path(:id => changeset, :text => "Comment #{count}"), :headers => auth_header
+          post changeset_comment_path(changeset, :text => "Comment #{count}"), :headers => auth_header
           assert_response :success
         end
       end
 
       assert_no_difference "ChangesetComment.count" do
-        post changeset_comment_path(:id => changeset, :text => "One comment too many"), :headers => auth_header
+        post changeset_comment_path(changeset, :text => "One comment too many"), :headers => auth_header
         assert_response :too_many_requests
       end
     end
@@ -164,13 +164,13 @@ module Api
 
       assert_difference "ChangesetComment.count", Settings.max_changeset_comments_per_hour do
         1.upto(Settings.max_changeset_comments_per_hour) do |count|
-          post changeset_comment_path(:id => changeset, :text => "Comment #{count}"), :headers => auth_header
+          post changeset_comment_path(changeset, :text => "Comment #{count}"), :headers => auth_header
           assert_response :success
         end
       end
 
       assert_no_difference "ChangesetComment.count" do
-        post changeset_comment_path(:id => changeset, :text => "One comment too many"), :headers => auth_header
+        post changeset_comment_path(changeset, :text => "One comment too many"), :headers => auth_header
         assert_response :too_many_requests
       end
     end
@@ -186,13 +186,13 @@ module Api
 
       assert_difference "ChangesetComment.count", Settings.initial_changeset_comments_per_hour / 2 do
         1.upto(Settings.initial_changeset_comments_per_hour / 2) do |count|
-          post changeset_comment_path(:id => changeset, :text => "Comment #{count}"), :headers => auth_header
+          post changeset_comment_path(changeset, :text => "Comment #{count}"), :headers => auth_header
           assert_response :success
         end
       end
 
       assert_no_difference "ChangesetComment.count" do
-        post changeset_comment_path(:id => changeset, :text => "One comment too many"), :headers => auth_header
+        post changeset_comment_path(changeset, :text => "One comment too many"), :headers => auth_header
         assert_response :too_many_requests
       end
     end
@@ -207,13 +207,13 @@ module Api
 
       assert_difference "ChangesetComment.count", Settings.moderator_changeset_comments_per_hour do
         1.upto(Settings.moderator_changeset_comments_per_hour) do |count|
-          post changeset_comment_path(:id => changeset, :text => "Comment #{count}"), :headers => auth_header
+          post changeset_comment_path(changeset, :text => "Comment #{count}"), :headers => auth_header
           assert_response :success
         end
       end
 
       assert_no_difference "ChangesetComment.count" do
-        post changeset_comment_path(:id => changeset, :text => "One comment too many"), :headers => auth_header
+        post changeset_comment_path(changeset, :text => "One comment too many"), :headers => auth_header
         assert_response :too_many_requests
       end
     end
@@ -303,11 +303,11 @@ module Api
     # But writing oauth tests is hard, and so it's easier to put in a controller test.)
     def test_api_write_and_terms_agreed_via_token
       user = create(:user, :terms_agreed => nil)
-      token = create(:access_token, :user => user, :allow_write_api => true)
+      token = create(:oauth_access_token, :resource_owner_id => user.id, :scopes => %w[write_api])
       changeset = create(:changeset, :closed)
 
       assert_difference "ChangesetComment.count", 0 do
-        signed_post changeset_comment_path(:id => changeset), :params => { :text => "This is a comment" }, :oauth => { :token => token }
+        post changeset_comment_path(changeset), :params => { :text => "This is a comment" }, :headers => bearer_authorization_header(token.token)
       end
       assert_response :forbidden
 
@@ -316,7 +316,7 @@ module Api
       user.save!
 
       assert_difference "ChangesetComment.count", 1 do
-        signed_post changeset_comment_path(:id => changeset), :params => { :text => "This is a comment" }, :oauth => { :token => token }
+        post changeset_comment_path(changeset), :params => { :text => "This is a comment" }, :headers => bearer_authorization_header(token.token)
       end
       assert_response :success
     end
@@ -330,7 +330,7 @@ module Api
       auth_header = basic_authorization_header user.email, "test"
 
       assert_difference "ChangesetComment.count", 0 do
-        post changeset_comment_path(:id => changeset, :text => "This is a comment"), :headers => auth_header
+        post changeset_comment_path(changeset, :text => "This is a comment"), :headers => auth_header
       end
       assert_response :forbidden
 
@@ -339,7 +339,7 @@ module Api
       user.save!
 
       assert_difference "ChangesetComment.count", 1 do
-        post changeset_comment_path(:id => changeset, :text => "This is a comment"), :headers => auth_header
+        post changeset_comment_path(changeset, :text => "This is a comment"), :headers => auth_header
       end
       assert_response :success
     end
index 8bb22929444de2e8da30460c5b190544419cc8d9..1d7afa03586130e5041b17a4722857a97f5561cf 100644 (file)
@@ -396,7 +396,7 @@ module Api
     # check that a changeset that doesn't exist returns an appropriate message
     def test_show_not_found
       [0, -32, 233455644, "afg", "213"].each do |id|
-        get changeset_show_path(:id => id)
+        get changeset_show_path(id)
         assert_response :not_found, "should get a not found"
       rescue ActionController::UrlGenerationError => e
         assert_match(/No route matches/, e.to_s)
@@ -424,7 +424,7 @@ module Api
       auth_header = basic_authorization_header user.email, "test"
 
       cs_id = changeset.id
-      put changeset_close_path(:id => cs_id), :headers => auth_header
+      put changeset_close_path(cs_id), :headers => auth_header
       assert_response :success
 
       # test that it really is closed now
@@ -470,7 +470,7 @@ module Api
 
       # First try to do it with no auth
       cs_ids.each do |id|
-        put changeset_close_path(:id => id)
+        put changeset_close_path(id)
         assert_response :unauthorized, "Shouldn't be able close the non-existant changeset #{id}, when not authorized"
       rescue ActionController::UrlGenerationError => e
         assert_match(/No route matches/, e.to_s)
@@ -479,7 +479,7 @@ module Api
       # Now try with auth
       auth_header = basic_authorization_header create(:user).email, "test"
       cs_ids.each do |id|
-        put changeset_close_path(:id => id), :headers => auth_header
+        put changeset_close_path(id), :headers => auth_header
         assert_response :not_found, "The changeset #{id} doesn't exist, so can't be closed"
       rescue ActionController::UrlGenerationError => e
         assert_match(/No route matches/, e.to_s)
@@ -636,26 +636,27 @@ module Api
                       "can't upload a simple valid creation to changeset: #{@response.body}"
 
       # check the returned payload
-      assert_select "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1
-      assert_select "diffResult>node", 1
-      assert_select "diffResult>way", 1
-      assert_select "diffResult>relation", 1
-
-      # inspect the response to find out what the new element IDs are
-      doc = XML::Parser.string(@response.body).parse
-      new_node_id = doc.find("//diffResult/node").first["new_id"].to_i
-      new_way_id = doc.find("//diffResult/way").first["new_id"].to_i
-      new_rel_id = doc.find("//diffResult/relation").first["new_id"].to_i
-
-      # check the old IDs are all present and negative one
-      assert_equal(-1, doc.find("//diffResult/node").first["old_id"].to_i)
-      assert_equal(-1, doc.find("//diffResult/way").first["old_id"].to_i)
-      assert_equal(-1, doc.find("//diffResult/relation").first["old_id"].to_i)
-
-      # check the versions are present and equal one
-      assert_equal 1, doc.find("//diffResult/node").first["new_version"].to_i
-      assert_equal 1, doc.find("//diffResult/way").first["new_version"].to_i
-      assert_equal 1, doc.find("//diffResult/relation").first["new_version"].to_i
+      new_node_id, new_way_id, new_rel_id = nil
+      assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
+        # inspect the response to find out what the new element IDs are
+        # check the old IDs are all present and negative one
+        # check the versions are present and equal one
+        assert_dom "> node", 1 do |(node_el)|
+          new_node_id = node_el["new_id"].to_i
+          assert_dom "> @old_id", "-1"
+          assert_dom "> @new_version", "1"
+        end
+        assert_dom "> way", 1 do |(way_el)|
+          new_way_id = way_el["new_id"].to_i
+          assert_dom "> @old_id", "-1"
+          assert_dom "> @new_version", "1"
+        end
+        assert_dom "> relation", 1 do |(rel_el)|
+          new_rel_id = rel_el["new_id"].to_i
+          assert_dom "> @old_id", "-1"
+          assert_dom "> @new_version", "1"
+        end
+      end
 
       # check that the changes made it into the database
       assert_equal 2, Node.find(new_node_id).tags.size, "new node should have two tags"
@@ -788,7 +789,7 @@ module Api
 
       # upload it, which used to cause an error like "PGError: ERROR:
       # integer out of range" (bug #2152). but shouldn't any more.
-      post changeset_upload_path(:id => changeset_id), :params => diff, :headers => auth_header
+      post changeset_upload_path(changeset_id), :params => diff, :headers => auth_header
       assert_response :success,
                       "can't upload a spatially-large diff to changeset: #{@response.body}"
 
@@ -878,28 +879,26 @@ module Api
                       "can't do a conditional delete of in use objects: #{@response.body}"
 
       # check the returned payload
-      assert_select "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1
-      assert_select "diffResult>node", 1
-      assert_select "diffResult>way", 1
-      assert_select "diffResult>relation", 1
-
-      # parse the response
-      doc = XML::Parser.string(@response.body).parse
-
-      # check the old IDs are all present and what we expect
-      assert_equal used_node.id, doc.find("//diffResult/node").first["old_id"].to_i
-      assert_equal used_way.id, doc.find("//diffResult/way").first["old_id"].to_i
-      assert_equal used_relation.id, doc.find("//diffResult/relation").first["old_id"].to_i
-
-      # check the new IDs are all present and unchanged
-      assert_equal used_node.id, doc.find("//diffResult/node").first["new_id"].to_i
-      assert_equal used_way.id, doc.find("//diffResult/way").first["new_id"].to_i
-      assert_equal used_relation.id, doc.find("//diffResult/relation").first["new_id"].to_i
-
-      # check the new versions are all present and unchanged
-      assert_equal used_node.version, doc.find("//diffResult/node").first["new_version"].to_i
-      assert_equal used_way.version, doc.find("//diffResult/way").first["new_version"].to_i
-      assert_equal used_relation.version, doc.find("//diffResult/relation").first["new_version"].to_i
+      assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
+        # check the old IDs are all present and what we expect
+        # check the new IDs are all present and unchanged
+        # check the new versions are all present and unchanged
+        assert_dom "> node", 1 do
+          assert_dom "> @old_id", used_node.id.to_s
+          assert_dom "> @new_id", used_node.id.to_s
+          assert_dom "> @new_version", used_node.version.to_s
+        end
+        assert_dom "> way", 1 do
+          assert_dom "> @old_id", used_way.id.to_s
+          assert_dom "> @new_id", used_way.id.to_s
+          assert_dom "> @new_version", used_way.version.to_s
+        end
+        assert_dom "> relation", 1 do
+          assert_dom "> @old_id", used_relation.id.to_s
+          assert_dom "> @new_id", used_relation.id.to_s
+          assert_dom "> @new_version", used_relation.version.to_s
+        end
+      end
 
       # check that nothing was, in fact, deleted
       assert Node.find(used_node.id).visible
@@ -973,14 +972,14 @@ module Api
                       "can't upload a complex diff to changeset: #{@response.body}"
 
       # check the returned payload
-      assert_select "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1
-      assert_select "diffResult>node", 1
-      assert_select "diffResult>way", 1
-      assert_select "diffResult>relation", 1
-
-      # inspect the response to find out what the new element IDs are
-      doc = XML::Parser.string(@response.body).parse
-      new_node_id = doc.find("//diffResult/node").first["new_id"].to_i
+      new_node_id = nil
+      assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
+        assert_dom "> node", 1 do |(node_el)|
+          new_node_id = node_el["new_id"].to_i
+        end
+        assert_dom "> way", 1
+        assert_dom "> relation", 1
+      end
 
       # check that the changes made it into the database
       assert_equal 2, Node.find(new_node_id).tags.size, "new node should have two tags"
@@ -1457,7 +1456,7 @@ module Api
       diff.root << modify
 
       # upload it
-      post changeset_upload_path(:id => changeset_id), :params => diff.to_s, :headers => auth_header
+      post changeset_upload_path(changeset_id), :params => diff.to_s, :headers => auth_header
       assert_response :success,
                       "diff should have uploaded OK"
 
@@ -1496,7 +1495,7 @@ module Api
       diff.root << modify
 
       # upload it
-      post changeset_upload_path(:id => changeset_id), :params => diff.to_s, :headers => auth_header
+      post changeset_upload_path(changeset_id), :params => diff.to_s, :headers => auth_header
       assert_response :success,
                       "diff should have uploaded OK"
 
@@ -1911,11 +1910,11 @@ module Api
       CHANGESET
 
       # upload it
-      post changeset_upload_path(:id => changeset_id), :params => diff, :headers => auth_header
+      post changeset_upload_path(changeset_id), :params => diff, :headers => auth_header
       assert_response :success,
                       "can't upload multiple versions of an element in a diff: #{@response.body}"
 
-      get changeset_download_path(:id => changeset_id)
+      get changeset_download_path(changeset_id)
       assert_response :success
 
       assert_select "osmChange", 1
@@ -1969,11 +1968,11 @@ module Api
       OSMFILE
 
       # upload it
-      post changeset_upload_path(:id => changeset_id), :params => diff, :headers => auth_header
+      post changeset_upload_path(changeset_id), :params => diff, :headers => auth_header
       assert_response :success,
                       "can't upload a diff from JOSM: #{@response.body}"
 
-      get changeset_download_path(:id => changeset_id)
+      get changeset_download_path(changeset_id)
       assert_response :success
 
       assert_select "osmChange", 1
@@ -2024,11 +2023,11 @@ module Api
       CHANGESET
 
       # upload it
-      post changeset_upload_path(:id => changeset_id), :params => diff, :headers => auth_header
+      post changeset_upload_path(changeset_id), :params => diff, :headers => auth_header
       assert_response :success,
                       "can't upload multiple versions of an element in a diff: #{@response.body}"
 
-      get changeset_download_path(:id => changeset_id)
+      get changeset_download_path(changeset_id)
       assert_response :success
 
       assert_select "osmChange", 1
@@ -2121,7 +2120,7 @@ module Api
       end
 
       # get the bounding box back from the changeset
-      get changeset_show_path(:id => changeset_id)
+      get changeset_show_path(changeset_id)
       assert_response :success, "Couldn't read back changeset."
       assert_select "osm>changeset[min_lon='0.1000000']", 1
       assert_select "osm>changeset[max_lon='0.1000000']", 1
@@ -2136,7 +2135,7 @@ module Api
       end
 
       # get the bounding box back from the changeset
-      get changeset_show_path(:id => changeset_id)
+      get changeset_show_path(changeset_id)
       assert_response :success, "Couldn't read back changeset for the second time."
       assert_select "osm>changeset[min_lon='0.1000000']", 1
       assert_select "osm>changeset[max_lon='0.2000000']", 1
@@ -2151,7 +2150,7 @@ module Api
       end
 
       # get the bounding box back from the changeset
-      get changeset_show_path(:id => changeset_id)
+      get changeset_show_path(changeset_id)
       assert_response :success, "Couldn't read back changeset for the third time."
       assert_select "osm>changeset[min_lon='0.1000000']", 1
       assert_select "osm>changeset[max_lon='0.3000000']", 1
@@ -2173,11 +2172,11 @@ module Api
 
       get changesets_path(:bbox => "-10,-10, 10, 10")
       assert_response :success, "can't get changesets in bbox"
-      assert_changesets [changeset2, changeset3]
+      assert_changesets_in_order [changeset3, changeset2]
 
       get changesets_path(:bbox => "4.5,4.5,4.6,4.6")
       assert_response :success, "can't get changesets in bbox"
-      assert_changesets [changeset3]
+      assert_changesets_in_order [changeset3]
 
       # not found when looking for changesets of non-existing users
       get changesets_path(:user => User.maximum(:id) + 1)
@@ -2197,11 +2196,11 @@ module Api
       auth_header = basic_authorization_header private_user.email, "test"
       get changesets_path(:user => private_user.id), :headers => auth_header
       assert_response :success, "can't get changesets by user ID"
-      assert_changesets [private_user_changeset, private_user_closed_changeset]
+      assert_changesets_in_order [private_user_changeset, private_user_closed_changeset]
 
       get changesets_path(:display_name => private_user.display_name), :headers => auth_header
       assert_response :success, "can't get changesets by user name"
-      assert_changesets [private_user_changeset, private_user_closed_changeset]
+      assert_changesets_in_order [private_user_changeset, private_user_closed_changeset]
 
       # test json endpoint
       get changesets_path(:display_name => private_user.display_name), :headers => auth_header, :params => { :format => "json" }
@@ -2221,39 +2220,39 @@ module Api
 
       get changesets_path(:user => private_user.id, :open => true), :headers => auth_header
       assert_response :success, "can't get changesets by user and open"
-      assert_changesets [private_user_changeset]
+      assert_changesets_in_order [private_user_changeset]
 
       get changesets_path(:time => "2007-12-31"), :headers => auth_header
       assert_response :success, "can't get changesets by time-since"
-      assert_changesets [private_user_changeset, private_user_closed_changeset, changeset, closed_changeset, changeset2, changeset3]
+      assert_changesets_in_order [changeset3, changeset2, changeset, private_user_changeset, private_user_closed_changeset, closed_changeset]
 
       get changesets_path(:time => "2008-01-01T12:34Z"), :headers => auth_header
       assert_response :success, "can't get changesets by time-since with hour"
-      assert_changesets [private_user_changeset, private_user_closed_changeset, changeset, closed_changeset, changeset2, changeset3]
+      assert_changesets_in_order [changeset3, changeset2, changeset, private_user_changeset, private_user_closed_changeset, closed_changeset]
 
       get changesets_path(:time => "2007-12-31T23:59Z,2008-01-02T00:01Z"), :headers => auth_header
       assert_response :success, "can't get changesets by time-range"
-      assert_changesets [closed_changeset]
+      assert_changesets_in_order [closed_changeset]
 
       get changesets_path(:open => "true"), :headers => auth_header
       assert_response :success, "can't get changesets by open-ness"
-      assert_changesets [private_user_changeset, changeset, changeset2, changeset3]
+      assert_changesets_in_order [changeset3, changeset2, changeset, private_user_changeset]
 
       get changesets_path(:closed => "true"), :headers => auth_header
       assert_response :success, "can't get changesets by closed-ness"
-      assert_changesets [private_user_closed_changeset, closed_changeset]
+      assert_changesets_in_order [private_user_closed_changeset, closed_changeset]
 
       get changesets_path(:closed => "true", :user => private_user.id), :headers => auth_header
       assert_response :success, "can't get changesets by closed-ness and user"
-      assert_changesets [private_user_closed_changeset]
+      assert_changesets_in_order [private_user_closed_changeset]
 
       get changesets_path(:closed => "true", :user => user.id), :headers => auth_header
       assert_response :success, "can't get changesets by closed-ness and user"
-      assert_changesets [closed_changeset]
+      assert_changesets_in_order [closed_changeset]
 
       get changesets_path(:changesets => "#{private_user_changeset.id},#{changeset.id},#{closed_changeset.id}"), :headers => auth_header
       assert_response :success, "can't get changesets by id (as comma-separated string)"
-      assert_changesets [private_user_changeset, changeset, closed_changeset]
+      assert_changesets_in_order [changeset, private_user_changeset, closed_changeset]
 
       get changesets_path(:changesets => ""), :headers => auth_header
       assert_response :bad_request, "should be a bad request since changesets is empty"
@@ -2642,7 +2641,7 @@ module Api
 
       # bad changeset id
       assert_no_difference "changeset.subscribers.count" do
-        post api_changeset_unsubscribe_path(:id => 999111), :headers => auth_header
+        post api_changeset_unsubscribe_path(999111), :headers => auth_header
       end
       assert_response :not_found
 
@@ -2683,15 +2682,6 @@ module Api
       end
     end
 
-    ##
-    # check that certain changesets exist in the output
-    def assert_changesets(changesets)
-      assert_select "osm>changeset", changesets.size
-      changesets.each do |changeset|
-        assert_select "osm>changeset[id='#{changeset.id}']", 1
-      end
-    end
-
     ##
     # check that certain changesets exist in the output in the specified order
     def assert_changesets_in_order(changesets)
diff --git a/test/controllers/api/messages_controller_test.rb b/test/controllers/api/messages_controller_test.rb
new file mode 100644 (file)
index 0000000..0b54be4
--- /dev/null
@@ -0,0 +1,611 @@
+require "test_helper"
+
+module Api
+  class MessagesControllerTest < ActionDispatch::IntegrationTest
+    ##
+    # test all routes which lead to this controller
+    def test_routes
+      assert_routing(
+        { :path => "/api/0.6/user/messages/inbox", :method => :get },
+        { :controller => "api/messages", :action => "inbox" }
+      )
+      assert_routing(
+        { :path => "/api/0.6/user/messages/inbox.xml", :method => :get },
+        { :controller => "api/messages", :action => "inbox", :format => "xml" }
+      )
+      assert_routing(
+        { :path => "/api/0.6/user/messages/inbox.json", :method => :get },
+        { :controller => "api/messages", :action => "inbox", :format => "json" }
+      )
+      assert_routing(
+        { :path => "/api/0.6/user/messages/outbox", :method => :get },
+        { :controller => "api/messages", :action => "outbox" }
+      )
+      assert_routing(
+        { :path => "/api/0.6/user/messages/outbox.xml", :method => :get },
+        { :controller => "api/messages", :action => "outbox", :format => "xml" }
+      )
+      assert_routing(
+        { :path => "/api/0.6/user/messages/outbox.json", :method => :get },
+        { :controller => "api/messages", :action => "outbox", :format => "json" }
+      )
+      assert_routing(
+        { :path => "/api/0.6/user/messages/1", :method => :get },
+        { :controller => "api/messages", :action => "show", :id => "1" }
+      )
+      assert_routing(
+        { :path => "/api/0.6/user/messages/1.xml", :method => :get },
+        { :controller => "api/messages", :action => "show", :id => "1", :format => "xml" }
+      )
+      assert_routing(
+        { :path => "/api/0.6/user/messages/1.json", :method => :get },
+        { :controller => "api/messages", :action => "show", :id => "1", :format => "json" }
+      )
+      assert_routing(
+        { :path => "/api/0.6/user/messages", :method => :post },
+        { :controller => "api/messages", :action => "create" }
+      )
+      assert_routing(
+        { :path => "/api/0.6/user/messages/1", :method => :post },
+        { :controller => "api/messages", :action => "update", :id => "1" }
+      )
+      assert_routing(
+        { :path => "/api/0.6/user/messages/1", :method => :delete },
+        { :controller => "api/messages", :action => "destroy", :id => "1" }
+      )
+    end
+
+    def test_create_success
+      recipient = create(:user)
+      sender = create(:user)
+
+      sender_token = create(:oauth_access_token,
+                            :resource_owner_id => sender.id,
+                            :scopes => %w[send_messages consume_messages])
+      sender_auth = bearer_authorization_header(sender_token.token)
+
+      msg = build(:message)
+
+      assert_difference "Message.count", 1 do
+        assert_difference "ActionMailer::Base.deliveries.size", 1 do
+          perform_enqueued_jobs do
+            post api_messages_path,
+                 :params => { :title => msg.title,
+                              :recipient_id => recipient.id,
+                              :body => msg.body,
+                              :format => "json" },
+                 :headers => sender_auth
+            assert_response :success
+          end
+        end
+      end
+
+      assert_equal "application/json", response.media_type
+      js = ActiveSupport::JSON.decode(@response.body)
+      jsm = js["message"]
+      assert_not_nil jsm
+      assert_not_nil jsm["id"]
+      assert_equal sender.id, jsm["from_user_id"]
+      assert_equal sender.display_name, jsm["from_display_name"]
+      assert_equal recipient.id, jsm["to_user_id"]
+      assert_equal recipient.display_name, jsm["to_display_name"]
+      assert_equal msg.title, jsm["title"]
+      assert_not_nil jsm["sent_on"]
+      assert_equal !msg.from_user_visible, jsm["deleted"]
+      assert_not jsm.key?("message_read")
+      assert_equal "markdown", jsm["body_format"]
+      assert_equal msg.body, jsm["body"]
+    end
+
+    def test_create_fail
+      recipient = create(:user)
+
+      sender = create(:user)
+      sender_token = create(:oauth_access_token,
+                            :resource_owner_id => sender.id,
+                            :scopes => %w[send_messages consume_messages])
+      sender_auth = bearer_authorization_header(sender_token.token)
+
+      assert_no_difference "Message.count" do
+        assert_no_difference "ActionMailer::Base.deliveries.size" do
+          perform_enqueued_jobs do
+            post api_messages_path,
+                 :params => { :title => "Title",
+                              :recipient_id => recipient.id,
+                              :body => "body" }
+          end
+        end
+      end
+      assert_response :unauthorized
+
+      assert_no_difference "Message.count" do
+        assert_no_difference "ActionMailer::Base.deliveries.size" do
+          perform_enqueued_jobs do
+            post api_messages_path,
+                 :params => { :recipient_id => recipient.id,
+                              :body => "body" },
+                 :headers => sender_auth
+          end
+        end
+      end
+      assert_response :bad_request
+
+      assert_no_difference "Message.count" do
+        assert_no_difference "ActionMailer::Base.deliveries.size" do
+          perform_enqueued_jobs do
+            post api_messages_path,
+                 :params => { :title => "Title",
+                              :body => "body" },
+                 :headers => sender_auth
+          end
+        end
+      end
+      assert_response :bad_request
+
+      assert_no_difference "Message.count" do
+        assert_no_difference "ActionMailer::Base.deliveries.size" do
+          perform_enqueued_jobs do
+            post api_messages_path,
+                 :params => { :title => "Title",
+                              :recipient_id => recipient.id },
+                 :headers => sender_auth
+          end
+        end
+      end
+      assert_response :bad_request
+    end
+
+    def test_show
+      recipient = create(:user)
+      sender = create(:user)
+      user3 = create(:user)
+
+      sender_token = create(:oauth_access_token,
+                            :resource_owner_id => sender.id,
+                            :scopes => %w[consume_messages])
+      sender_auth = bearer_authorization_header(sender_token.token)
+
+      recipient_token = create(:oauth_access_token,
+                               :resource_owner_id => recipient.id,
+                               :scopes => %w[consume_messages])
+      recipient_auth = bearer_authorization_header(recipient_token.token)
+
+      user3_token = create(:oauth_access_token,
+                           :resource_owner_id => user3.id,
+                           :scopes => %w[send_messages consume_messages])
+      user3_auth = bearer_authorization_header(user3_token.token)
+
+      msg = create(:message, :unread, :sender => sender, :recipient => recipient)
+
+      # fail if not authorized
+      get api_message_path(:id => msg.id)
+      assert_response :unauthorized
+
+      # only recipient and sender can read the message
+      get api_message_path(:id => msg.id), :headers => user3_auth
+      assert_response :forbidden
+
+      # message does not exist
+      get api_message_path(:id => 99999), :headers => user3_auth
+      assert_response :not_found
+
+      # verify xml output
+      get api_message_path(:id => msg.id), :headers => recipient_auth
+      assert_equal "application/xml", response.media_type
+      assert_select "message", :count => 1 do
+        assert_select "[id='#{msg.id}']"
+        assert_select "[from_user_id='#{sender.id}']"
+        assert_select "[from_display_name='#{sender.display_name}']"
+        assert_select "[to_user_id='#{recipient.id}']"
+        assert_select "[to_display_name='#{recipient.display_name}']"
+        assert_select "[sent_on]"
+        assert_select "[deleted='#{!msg.to_user_visible}']"
+        assert_select "[message_read='#{msg.message_read}']"
+        assert_select "[body_format='markdown']"
+        assert_select "title", msg.title
+        assert_select "body", msg.body
+      end
+
+      # verify json output
+      get api_message_path(:id => msg.id, :format => "json"), :headers => recipient_auth
+      assert_equal "application/json", response.media_type
+      js = ActiveSupport::JSON.decode(@response.body)
+      jsm = js["message"]
+      assert_not_nil jsm
+      assert_equal msg.id, jsm["id"]
+      assert_equal sender.id, jsm["from_user_id"]
+      assert_equal sender.display_name, jsm["from_display_name"]
+      assert_equal recipient.id, jsm["to_user_id"]
+      assert_equal recipient.display_name, jsm["to_display_name"]
+      assert_equal msg.title, jsm["title"]
+      assert_not_nil jsm["sent_on"]
+      assert_equal msg.message_read, jsm["message_read"]
+      assert_equal !msg.to_user_visible, jsm["deleted"]
+      assert_equal "markdown", jsm["body_format"]
+      assert_equal msg.body, jsm["body"]
+
+      get api_message_path(:id => msg.id), :headers => sender_auth
+      assert_equal "application/xml", response.media_type
+      assert_select "message", :count => 1 do
+        assert_select "[id='#{msg.id}']"
+        assert_select "[from_user_id='#{sender.id}']"
+        assert_select "[from_display_name='#{sender.display_name}']"
+        assert_select "[to_user_id='#{recipient.id}']"
+        assert_select "[to_display_name='#{recipient.display_name}']"
+        assert_select "[sent_on]"
+        assert_select "[deleted='#{!msg.from_user_visible}']"
+        assert_select "[message_read='#{msg.message_read}']", 0
+        assert_select "[body_format='markdown']"
+        assert_select "title", msg.title
+        assert_select "body", msg.body
+      end
+
+      # verify json output
+      get api_message_path(:id => msg.id, :format => "json"), :headers => sender_auth
+      assert_equal "application/json", response.media_type
+      js = ActiveSupport::JSON.decode(@response.body)
+      jsm = js["message"]
+      assert_not_nil jsm
+      assert_equal msg.id, jsm["id"]
+      assert_equal sender.id, jsm["from_user_id"]
+      assert_equal sender.display_name, jsm["from_display_name"]
+      assert_equal recipient.id, jsm["to_user_id"]
+      assert_equal recipient.display_name, jsm["to_display_name"]
+      assert_equal msg.title, jsm["title"]
+      assert_not_nil jsm["sent_on"]
+      assert_equal !msg.from_user_visible, jsm["deleted"]
+      assert_not jsm.key?("message_read")
+      assert_equal "markdown", jsm["body_format"]
+      assert_equal msg.body, jsm["body"]
+    end
+
+    def test_update_status
+      recipient = create(:user)
+      sender = create(:user)
+      user3 = create(:user)
+
+      recipient_token = create(:oauth_access_token,
+                               :resource_owner_id => recipient.id,
+                               :scopes => %w[consume_messages])
+      recipient_auth = bearer_authorization_header(recipient_token.token)
+
+      user3_token = create(:oauth_access_token,
+                           :resource_owner_id => user3.id,
+                           :scopes => %w[send_messages consume_messages])
+      user3_auth = bearer_authorization_header(user3_token.token)
+
+      msg = create(:message, :unread, :sender => sender, :recipient => recipient)
+
+      # attempt to mark message as read by recipient, not authenticated
+      post api_message_path(:id => msg.id), :params => { :read_status => true }
+      assert_response :unauthorized
+
+      # attempt to mark message as read by recipient, not allowed
+      post api_message_path(:id => msg.id), :params => { :read_status => true }, :headers => user3_auth
+      assert_response :forbidden
+
+      # missing parameter
+      post api_message_path(:id => msg.id), :headers => recipient_auth
+      assert_response :bad_request
+
+      # wrong type of parameter
+      post api_message_path(:id => msg.id),
+           :params => { :read_status => "not a boolean" },
+           :headers => recipient_auth
+      assert_response :bad_request
+
+      # mark message as read by recipient
+      post api_message_path(:id => msg.id, :format => "json"),
+           :params => { :read_status => true },
+           :headers => recipient_auth
+      assert_response :success
+      assert_equal "application/json", response.media_type
+      js = ActiveSupport::JSON.decode(@response.body)
+      jsm = js["message"]
+      assert_not_nil jsm
+      assert_equal msg.id, jsm["id"]
+      assert_equal sender.id, jsm["from_user_id"]
+      assert_equal sender.display_name, jsm["from_display_name"]
+      assert_equal recipient.id, jsm["to_user_id"]
+      assert_equal recipient.display_name, jsm["to_display_name"]
+      assert_equal msg.title, jsm["title"]
+      assert_not_nil jsm["sent_on"]
+      assert jsm["message_read"]
+      assert_equal !msg.to_user_visible, jsm["deleted"]
+      assert_equal "markdown", jsm["body_format"]
+      assert_equal msg.body, jsm["body"]
+
+      # mark message as unread by recipient
+      post api_message_path(:id => msg.id, :format => "json"),
+           :params => { :read_status => false },
+           :headers => recipient_auth
+      assert_response :success
+      assert_equal "application/json", response.media_type
+      js = ActiveSupport::JSON.decode(@response.body)
+      jsm = js["message"]
+      assert_not_nil jsm
+      assert_equal msg.id, jsm["id"]
+      assert_equal sender.id, jsm["from_user_id"]
+      assert_equal sender.display_name, jsm["from_display_name"]
+      assert_equal recipient.id, jsm["to_user_id"]
+      assert_equal recipient.display_name, jsm["to_display_name"]
+      assert_equal msg.title, jsm["title"]
+      assert_not_nil jsm["sent_on"]
+      assert_not jsm["message_read"]
+      assert_equal !msg.to_user_visible, jsm["deleted"]
+      assert_equal "markdown", jsm["body_format"]
+      assert_equal msg.body, jsm["body"]
+    end
+
+    def test_delete
+      recipient = create(:user)
+      recipient_token = create(:oauth_access_token,
+                               :resource_owner_id => recipient.id,
+                               :scopes => %w[consume_messages])
+      recipient_auth = bearer_authorization_header(recipient_token.token)
+
+      sender = create(:user)
+      sender_token = create(:oauth_access_token,
+                            :resource_owner_id => sender.id,
+                            :scopes => %w[send_messages consume_messages])
+      sender_auth = bearer_authorization_header(sender_token.token)
+
+      user3 = create(:user)
+      user3_token = create(:oauth_access_token,
+                           :resource_owner_id => user3.id,
+                           :scopes => %w[send_messages consume_messages])
+      user3_auth = bearer_authorization_header(user3_token.token)
+
+      msg = create(:message, :read, :sender => sender, :recipient => recipient)
+
+      # attempt to delete message, not authenticated
+      delete api_message_path(:id => msg.id)
+      assert_response :unauthorized
+
+      # attempt to delete message, by user3
+      delete api_message_path(:id => msg.id), :headers => user3_auth
+      assert_response :forbidden
+
+      # delete message by recipient
+      delete api_message_path(:id => msg.id, :format => "json"), :headers => recipient_auth
+      assert_response :success
+      assert_equal "application/json", response.media_type
+      js = ActiveSupport::JSON.decode(@response.body)
+      jsm = js["message"]
+      assert_not_nil jsm
+      assert_equal msg.id, jsm["id"]
+      assert_equal sender.id, jsm["from_user_id"]
+      assert_equal sender.display_name, jsm["from_display_name"]
+      assert_equal recipient.id, jsm["to_user_id"]
+      assert_equal recipient.display_name, jsm["to_display_name"]
+      assert_equal msg.title, jsm["title"]
+      assert_not_nil jsm["sent_on"]
+      assert_equal msg.message_read, jsm["message_read"]
+      assert jsm["deleted"]
+      assert_equal "markdown", jsm["body_format"]
+      assert_equal msg.body, jsm["body"]
+
+      # delete message by sender
+      delete api_message_path(:id => msg.id, :format => "json"), :headers => sender_auth
+      assert_response :success
+      assert_equal "application/json", response.media_type
+      js = ActiveSupport::JSON.decode(@response.body)
+      jsm = js["message"]
+      assert_not_nil jsm
+      assert_equal msg.id, jsm["id"]
+      assert_equal sender.id, jsm["from_user_id"]
+      assert_equal sender.display_name, jsm["from_display_name"]
+      assert_equal recipient.id, jsm["to_user_id"]
+      assert_equal recipient.display_name, jsm["to_display_name"]
+      assert_equal msg.title, jsm["title"]
+      assert_not_nil jsm["sent_on"]
+      assert jsm["deleted"]
+      assert_not jsm.key?("message_read")
+      assert_equal "markdown", jsm["body_format"]
+      assert_equal msg.body, jsm["body"]
+    end
+
+    def test_list_messages
+      user1 = create(:user)
+      user1_token = create(:oauth_access_token,
+                           :resource_owner_id => user1.id,
+                           :scopes => %w[send_messages consume_messages])
+      user1_auth = bearer_authorization_header(user1_token.token)
+
+      user2 = create(:user)
+      user2_token = create(:oauth_access_token,
+                           :resource_owner_id => user2.id,
+                           :scopes => %w[send_messages consume_messages])
+      user2_auth = bearer_authorization_header(user2_token.token)
+
+      user3 = create(:user)
+      user3_token = create(:oauth_access_token,
+                           :resource_owner_id => user3.id,
+                           :scopes => %w[send_messages consume_messages])
+      user3_auth = bearer_authorization_header(user3_token.token)
+
+      # create some messages between users
+      # user | inbox | outbox
+      #   1  |   0   |   3
+      #   2  |   2   |   1
+      #   3  |   2   |   0
+      create(:message, :unread, :sender => user1, :recipient => user2)
+      create(:message, :unread, :sender => user1, :recipient => user2)
+      create(:message, :unread, :sender => user1, :recipient => user3)
+      create(:message, :unread, :sender => user2, :recipient => user3)
+
+      # only authorized users
+      get inbox_api_messages_path
+      assert_response :unauthorized
+      get outbox_api_messages_path
+      assert_response :unauthorized
+
+      # no messages in user1.inbox
+      get inbox_api_messages_path, :headers => user1_auth
+      assert_response :success
+      assert_equal "application/xml", response.media_type
+      assert_select "message", :count => 0
+
+      # 3 messages in user1.outbox
+      get outbox_api_messages_path, :headers => user1_auth
+      assert_response :success
+      assert_equal "application/xml", response.media_type
+      assert_select "message", :count => 3 do
+        assert_select "[from_user_id='#{user1.id}']"
+        assert_select "[from_display_name='#{user1.display_name}']"
+        assert_select "[to_user_id]"
+        assert_select "[to_display_name]"
+        assert_select "[sent_on]"
+        assert_select "[message_read]", 0
+        assert_select "[deleted='false']"
+        assert_select "[body_format]"
+        assert_select "body", false
+        assert_select "title"
+      end
+
+      # 2 messages in user2.inbox
+      get inbox_api_messages_path, :headers => user2_auth
+      assert_response :success
+      assert_equal "application/xml", response.media_type
+      assert_select "message", :count => 2 do
+        assert_select "[from_user_id]"
+        assert_select "[from_display_name]"
+        assert_select "[to_user_id='#{user2.id}']"
+        assert_select "[to_display_name='#{user2.display_name}']"
+        assert_select "[sent_on]"
+        assert_select "[message_read='false']"
+        assert_select "[deleted='false']"
+        assert_select "[body_format]"
+        assert_select "body", false
+        assert_select "title"
+      end
+
+      # 1 message in user2.outbox
+      get outbox_api_messages_path, :headers => user2_auth
+      assert_response :success
+      assert_equal "application/xml", response.media_type
+      assert_select "message", :count => 1 do
+        assert_select "[from_user_id='#{user2.id}']"
+        assert_select "[from_display_name='#{user2.display_name}']"
+        assert_select "[to_user_id]"
+        assert_select "[to_display_name]"
+        assert_select "[sent_on]"
+        assert_select "[deleted='false']"
+        assert_select "[message_read]", 0
+        assert_select "[body_format]"
+        assert_select "body", false
+        assert_select "title"
+      end
+
+      # 2 messages in user3.inbox
+      get inbox_api_messages_path, :headers => user3_auth
+      assert_response :success
+      assert_equal "application/xml", response.media_type
+      assert_select "message", :count => 2 do
+        assert_select "[from_user_id]"
+        assert_select "[from_display_name]"
+        assert_select "[to_user_id='#{user3.id}']"
+        assert_select "[to_display_name='#{user3.display_name}']"
+        assert_select "[sent_on]"
+        assert_select "[message_read='false']"
+        assert_select "[deleted='false']"
+        assert_select "[body_format]"
+        assert_select "body", false
+        assert_select "title"
+      end
+
+      # 0 messages in user3.outbox
+      get outbox_api_messages_path, :headers => user3_auth
+      assert_response :success
+      assert_equal "application/xml", response.media_type
+      assert_select "message", :count => 0
+    end
+
+    def test_paged_list_messages_asc
+      recipient = create(:user)
+      recipient_token = create(:oauth_access_token,
+                               :resource_owner_id => recipient.id,
+                               :scopes => %w[consume_messages])
+      recipient_auth = bearer_authorization_header(recipient_token.token)
+
+      sender = create(:user)
+
+      create_list(:message, 100, :unread, :sender => sender, :recipient => recipient)
+
+      msgs_read = {}
+      params = { :order => "oldest", :limit => 20 }
+      10.times do
+        get inbox_api_messages_path(:format => "json"),
+            :params => params,
+            :headers => recipient_auth
+        assert_response :success
+        assert_equal "application/json", response.media_type
+        js = ActiveSupport::JSON.decode(@response.body)
+        jsm = js["messages"]
+        assert_operator jsm.count, :<=, 20
+
+        break if jsm.nil? || jsm.count.zero?
+
+        assert_operator(jsm[0]["id"], :>=, params[:from_id]) unless params[:from_id].nil?
+        # ensure ascending order
+        (0..jsm.count - 1).each do |i|
+          assert_operator(jsm[i]["id"], :<, jsm[i + 1]["id"]) unless i == jsm.count - 1
+          msgs_read[jsm[i]["id"]] = jsm[i]
+        end
+        params[:from_id] = jsm[jsm.count - 1]["id"]
+      end
+      assert_equal 100, msgs_read.count
+    end
+
+    def test_paged_list_messages_desc
+      recipient = create(:user)
+      recipient_token = create(:oauth_access_token,
+                               :resource_owner_id => recipient.id,
+                               :scopes => %w[consume_messages])
+      recipient_auth = bearer_authorization_header(recipient_token.token)
+
+      sender = create(:user)
+
+      create_list(:message, 100, :unread, :sender => sender, :recipient => recipient)
+
+      real_max_id = -1
+      msgs_read = {}
+      params = { :order => "newest", :limit => 20 }
+      10.times do
+        get inbox_api_messages_path(:format => "json"),
+            :params => params,
+            :headers => recipient_auth
+        assert_response :success
+        assert_equal "application/json", response.media_type
+        js = ActiveSupport::JSON.decode(@response.body)
+        jsm = js["messages"]
+        assert_operator jsm.count, :<=, 20
+
+        break if jsm.nil? || jsm.count.zero?
+
+        if params[:from_id].nil?
+          real_max_id = jsm[0]["id"]
+        else
+          assert_operator jsm[0]["id"], :<=, params[:from_id]
+        end
+        # ensure descending order
+        (0..jsm.count - 1).each do |i|
+          assert_operator(jsm[i]["id"], :>, jsm[i + 1]["id"]) unless i == jsm.count - 1
+          msgs_read[jsm[i]["id"]] = jsm[i]
+        end
+        params[:from_id] = jsm[jsm.count - 1]["id"]
+      end
+      assert_equal 100, msgs_read.count
+      assert_not_equal(-1, real_max_id)
+
+      # invoke without min_id/max_id parameters, verify that we get the last batch
+      get inbox_api_messages_path(:format => "json"), :params => { :limit => 20 }, :headers => recipient_auth
+      assert_response :success
+      assert_equal "application/json", response.media_type
+      js = ActiveSupport::JSON.decode(@response.body)
+      jsm = js["messages"]
+      assert_not_nil jsm
+      assert_equal real_max_id, jsm[0]["id"]
+    end
+  end
+end
index 5fde0277cf8d34bc12aac31fc60a6c77d0489c10..d70c92861e9b563f7df5eab1fb933dfce1ead943 100644 (file)
@@ -297,6 +297,8 @@ module Api
     # tests whether the API works and prevents incorrect use while trying
     # to update nodes.
     def test_update
+      invalid_attr_values = [["lat", 91.0], ["lat", -91.0], ["lon", 181.0], ["lon", -181.0]]
+
       ## First test with no user credentials
       # try and update a node without authorisation
       # first try to delete node without auth
@@ -334,21 +336,11 @@ module Api
       assert_require_public_data "update with changeset=0 should be forbidden, when data isn't public"
 
       ## try and submit invalid updates
-      xml = xml_attr_rewrite(xml_for_node(private_node), "lat", 91.0)
-      put api_node_path(private_node), :params => xml.to_s, :headers => auth_header
-      assert_require_public_data "node at lat=91 should be forbidden, when data isn't public"
-
-      xml = xml_attr_rewrite(xml_for_node(private_node), "lat", -91.0)
-      put api_node_path(private_node), :params => xml.to_s, :headers => auth_header
-      assert_require_public_data "node at lat=-91 should be forbidden, when data isn't public"
-
-      xml = xml_attr_rewrite(xml_for_node(private_node), "lon", 181.0)
-      put api_node_path(private_node), :params => xml.to_s, :headers => auth_header
-      assert_require_public_data "node at lon=181 should be forbidden, when data isn't public"
-
-      xml = xml_attr_rewrite(xml_for_node(private_node), "lon", -181.0)
-      put api_node_path(private_node), :params => xml.to_s, :headers => auth_header
-      assert_require_public_data "node at lon=-181 should be forbidden, when data isn't public"
+      invalid_attr_values.each do |name, value|
+        xml = xml_attr_rewrite(xml_for_node(private_node), name, value)
+        put api_node_path(private_node), :params => xml.to_s, :headers => auth_header
+        assert_require_public_data "node at #{name}=#{value} should be forbidden, when data isn't public"
+      end
 
       ## finally, produce a good request which still won't work
       xml = xml_for_node(private_node)
@@ -386,21 +378,11 @@ module Api
       assert_response :conflict, "update with changeset=0 should be rejected"
 
       ## try and submit invalid updates
-      xml = xml_attr_rewrite(xml_for_node(node), "lat", 91.0)
-      put api_node_path(node), :params => xml.to_s, :headers => auth_header
-      assert_response :bad_request, "node at lat=91 should be rejected"
-
-      xml = xml_attr_rewrite(xml_for_node(node), "lat", -91.0)
-      put api_node_path(node), :params => xml.to_s, :headers => auth_header
-      assert_response :bad_request, "node at lat=-91 should be rejected"
-
-      xml = xml_attr_rewrite(xml_for_node(node), "lon", 181.0)
-      put api_node_path(node), :params => xml.to_s, :headers => auth_header
-      assert_response :bad_request, "node at lon=181 should be rejected"
-
-      xml = xml_attr_rewrite(xml_for_node(node), "lon", -181.0)
-      put api_node_path(node), :params => xml.to_s, :headers => auth_header
-      assert_response :bad_request, "node at lon=-181 should be rejected"
+      invalid_attr_values.each do |name, value|
+        xml = xml_attr_rewrite(xml_for_node(node), name, value)
+        put api_node_path(node), :params => xml.to_s, :headers => auth_header
+        assert_response :bad_request, "node at #{name}=#{value} should be rejected"
+      end
 
       ## next, attack the versioning
       current_node_version = node.version
index 982df1dd7e5706bc4c5f17f9c39656a4e3a55b44..eba3d255ef800d28cab49956699fd25237ffb132 100644 (file)
@@ -1089,7 +1089,7 @@ module Api
 
       # now download the changeset to check its bounding box
       with_controller(Api::ChangesetsController.new) do
-        get changeset_show_path(:id => changeset_id)
+        get changeset_show_path(changeset_id)
         assert_response :success, "can't re-read changeset for modify test"
         assert_select "osm>changeset", 1, "Changeset element doesn't exist in #{@response.body}"
         assert_select "osm>changeset[id='#{changeset_id}']", 1, "Changeset id=#{changeset_id} doesn't exist in #{@response.body}"
@@ -1153,7 +1153,7 @@ module Api
         change << modify
         modify << doc.import(rel.find("//osm/relation").first)
 
-        post changeset_upload_path(:id => cs_id), :params => doc.to_s, :headers => headers
+        post changeset_upload_path(cs_id), :params => doc.to_s, :headers => headers
         assert_response :success, "can't upload diff relation: #{@response.body}"
         version = xml_parse(@response.body).find("//diffResult/relation").first["new_version"].to_i
       end
index 4e96d4ce9146a8d6227c16280980e659d258987f..41406e1b3d22413b50e07850dadf3ac91f29aacc 100644 (file)
@@ -252,10 +252,10 @@ module Api
     # read preferences
     def test_show_using_token
       user = create(:user)
-      token = create(:access_token, :user => user, :allow_read_prefs => true)
+      token = create(:oauth_access_token, :resource_owner_id => user.id, :scopes => %w[read_prefs])
       create(:user_preference, :user => user, :k => "key", :v => "value")
 
-      signed_get user_preference_path(:preference_key => "key"), :oauth => { :token => token }
+      get user_preference_path(:preference_key => "key"), :headers => bearer_authorization_header(token.token)
       assert_response :success
     end
 
@@ -264,10 +264,10 @@ module Api
     # by other methods.
     def test_show_using_token_fail
       user = create(:user)
-      token = create(:access_token, :user => user, :allow_read_prefs => false)
+      token = create(:oauth_access_token, :resource_owner_id => user.id)
       create(:user_preference, :user => user, :k => "key", :v => "value")
 
-      signed_get user_preference_path(:preference_key => "key"), :oauth => { :token => token }
+      get user_preference_path(:preference_key => "key"), :headers => bearer_authorization_header(token.token)
       assert_response :forbidden
     end
   end
index bb6c25781fc5bd6aa6a31de5976bd31e74c4c0ef..e3bbb490dfdf3c56a4d566647405379dd7db5571 100644 (file)
@@ -119,9 +119,9 @@ class DiaryEntriesControllerTest < ActionDispatch::IntegrationTest
         assert_select "input#latitude[name='diary_entry[latitude]']", :count => 1
         assert_select "input#longitude[name='diary_entry[longitude]']", :count => 1
         assert_select "input[name=commit][type=submit][value=Publish]", :count => 1
-        assert_select "input[name=commit][type=submit][value=Edit]", :count => 1
-        assert_select "input[name=commit][type=submit][value=Preview]", :count => 1
-        assert_select "input", :count => 6
+        assert_select "button[type=button]", :text => "Edit", :count => 1
+        assert_select "button[type=button]", :text => "Preview", :count => 1
+        assert_select "input", :count => 4
       end
     end
   end
@@ -272,9 +272,9 @@ class DiaryEntriesControllerTest < ActionDispatch::IntegrationTest
         assert_select "input#latitude[name='diary_entry[latitude]']", :count => 1
         assert_select "input#longitude[name='diary_entry[longitude]']", :count => 1
         assert_select "input[name=commit][type=submit][value=Update]", :count => 1
-        assert_select "input[name=commit][type=submit][value=Edit]", :count => 1
-        assert_select "input[name=commit][type=submit][value=Preview]", :count => 1
-        assert_select "input", :count => 7
+        assert_select "button[type=button]", :text => "Edit", :count => 1
+        assert_select "button[type=button]", :text => "Preview", :count => 1
+        assert_select "input", :count => 5
       end
     end
 
@@ -657,6 +657,9 @@ class DiaryEntriesControllerTest < ActionDispatch::IntegrationTest
     assert_dom "head meta[property='og:image']" do
       assert_dom "> @content", ActionController::Base.helpers.image_url("osm_logo_256.png", :host => root_url)
     end
+    assert_dom "head meta[property='og:image:alt']" do
+      assert_dom "> @content", "OpenStreetMap logo"
+    end
   end
 
   def test_show_og_image
@@ -668,6 +671,9 @@ class DiaryEntriesControllerTest < ActionDispatch::IntegrationTest
     assert_dom "head meta[property='og:image']" do
       assert_dom "> @content", "https://example.com/picture.jpg"
     end
+    assert_dom "head meta[property='og:image:alt']" do
+      assert_dom "> @content", "some picture"
+    end
   end
 
   def test_show_og_image_with_relative_uri
@@ -679,6 +685,9 @@ class DiaryEntriesControllerTest < ActionDispatch::IntegrationTest
     assert_dom "head meta[property='og:image']" do
       assert_dom "> @content", "#{root_url}picture.jpg"
     end
+    assert_dom "head meta[property='og:image:alt']" do
+      assert_dom "> @content", "some local picture"
+    end
   end
 
   def test_show_og_image_with_spaces
@@ -690,6 +699,9 @@ class DiaryEntriesControllerTest < ActionDispatch::IntegrationTest
     assert_dom "head meta[property='og:image']" do
       assert_dom "> @content", "https://example.com/the%20picture.jpg"
     end
+    assert_dom "head meta[property='og:image:alt']" do
+      assert_dom "> @content", "some picture"
+    end
   end
 
   def test_show_og_image_with_relative_uri_and_spaces
@@ -701,6 +713,9 @@ class DiaryEntriesControllerTest < ActionDispatch::IntegrationTest
     assert_dom "head meta[property='og:image']" do
       assert_dom "> @content", "#{root_url}the%20picture.jpg"
     end
+    assert_dom "head meta[property='og:image:alt']" do
+      assert_dom "> @content", "some local picture"
+    end
   end
 
   def test_show_og_image_with_invalid_uri
@@ -712,6 +727,21 @@ class DiaryEntriesControllerTest < ActionDispatch::IntegrationTest
     assert_dom "head meta[property='og:image']" do
       assert_dom "> @content", ActionController::Base.helpers.image_url("osm_logo_256.png", :host => root_url)
     end
+    assert_dom "head meta[property='og:image:alt']" do
+      assert_dom "> @content", "OpenStreetMap logo"
+    end
+  end
+
+  def test_show_og_image_without_alt
+    user = create(:user)
+    diary_entry = create(:diary_entry, :user => user, :body => "<img src='https://example.com/no_alt.gif'>")
+
+    get diary_entry_path(user, diary_entry)
+    assert_response :success
+    assert_dom "head meta[property='og:image']" do
+      assert_dom "> @content", "https://example.com/no_alt.gif"
+    end
+    assert_dom "head meta[property='og:image:alt']", :count => 0
   end
 
   def test_hide
index a988fc909f7cc3a73ad3417db5ca43958d8c4b01..167bcc7b6ab5ffd2123febf1987d0ee198d004a9 100644 (file)
@@ -27,22 +27,22 @@ class IssuesControllerTest < ActionDispatch::IntegrationTest
     issue = create(:issue, :reportable => target_user, :reported_user => target_user, :assigned_role => "moderator")
 
     # Access issue without login
-    get issue_path(:id => issue)
+    get issue_path(issue)
     assert_redirected_to login_path(:referer => issue_path(issue))
 
     # Access issue as normal user
     session_for(create(:user))
-    get issue_path(:id => issue)
+    get issue_path(issue)
     assert_redirected_to :controller => :errors, :action => :forbidden
 
     # Access issue as administrator
     session_for(create(:administrator_user))
-    get issue_path(:id => issue)
+    get issue_path(issue)
     assert_redirected_to :controller => :errors, :action => :not_found
 
     # Access issue as moderator
     session_for(create(:moderator_user))
-    get issue_path(:id => issue)
+    get issue_path(issue)
     assert_response :success
   end
 
@@ -51,22 +51,22 @@ class IssuesControllerTest < ActionDispatch::IntegrationTest
     issue = create(:issue, :reportable => target_user, :reported_user => target_user, :assigned_role => "administrator")
 
     # Access issue without login
-    get issue_path(:id => issue)
+    get issue_path(issue)
     assert_redirected_to login_path(:referer => issue_path(issue))
 
     # Access issue as normal user
     session_for(create(:user))
-    get issue_path(:id => issue)
+    get issue_path(issue)
     assert_redirected_to :controller => :errors, :action => :forbidden
 
     # Access issue as moderator
     session_for(create(:moderator_user))
-    get issue_path(:id => issue)
+    get issue_path(issue)
     assert_redirected_to :controller => :errors, :action => :not_found
 
     # Access issue as administrator
     session_for(create(:administrator_user))
-    get issue_path(:id => issue)
+    get issue_path(issue)
     assert_response :success
   end
 
@@ -75,23 +75,23 @@ class IssuesControllerTest < ActionDispatch::IntegrationTest
     issue = create(:issue, :reportable => target_user, :reported_user => target_user, :assigned_role => "moderator")
 
     # Resolve issue without login
-    post resolve_issue_path(:id => issue)
+    post resolve_issue_path(issue)
     assert_response :forbidden
 
     # Resolve issue as normal user
     session_for(create(:user))
-    post resolve_issue_path(:id => issue)
+    post resolve_issue_path(issue)
     assert_redirected_to :controller => :errors, :action => :forbidden
 
     # Resolve issue as administrator
     session_for(create(:administrator_user))
-    post resolve_issue_path(:id => issue)
+    post resolve_issue_path(issue)
     assert_redirected_to :controller => :errors, :action => :not_found
-    assert_not issue.reload.resolved?
+    assert_not_predicate issue.reload, :resolved?
 
     # Resolve issue as moderator
     session_for(create(:moderator_user))
-    post resolve_issue_path(:id => issue)
+    post resolve_issue_path(issue)
     assert_response :redirect
     assert_predicate issue.reload, :resolved?
   end
@@ -101,23 +101,23 @@ class IssuesControllerTest < ActionDispatch::IntegrationTest
     issue = create(:issue, :reportable => target_user, :reported_user => target_user, :assigned_role => "administrator")
 
     # Resolve issue without login
-    post resolve_issue_path(:id => issue)
+    post resolve_issue_path(issue)
     assert_response :forbidden
 
     # Resolve issue as normal user
     session_for(create(:user))
-    post resolve_issue_path(:id => issue)
+    post resolve_issue_path(issue)
     assert_redirected_to :controller => :errors, :action => :forbidden
 
     # Resolve issue as moderator
     session_for(create(:moderator_user))
-    post resolve_issue_path(:id => issue)
+    post resolve_issue_path(issue)
     assert_redirected_to :controller => :errors, :action => :not_found
-    assert_not issue.reload.resolved?
+    assert_not_predicate issue.reload, :resolved?
 
     # Resolve issue as administrator
     session_for(create(:administrator_user))
-    post resolve_issue_path(:id => issue)
+    post resolve_issue_path(issue)
     assert_response :redirect
     assert_predicate issue.reload, :resolved?
   end
@@ -127,23 +127,23 @@ class IssuesControllerTest < ActionDispatch::IntegrationTest
     issue = create(:issue, :reportable => target_user, :reported_user => target_user, :assigned_role => "moderator")
 
     # Ignore issue without login
-    post ignore_issue_path(:id => issue)
+    post ignore_issue_path(issue)
     assert_response :forbidden
 
     # Ignore issue as normal user
     session_for(create(:user))
-    post ignore_issue_path(:id => issue)
+    post ignore_issue_path(issue)
     assert_redirected_to :controller => :errors, :action => :forbidden
 
     # Ignore issue as administrator
     session_for(create(:administrator_user))
-    post ignore_issue_path(:id => issue)
+    post ignore_issue_path(issue)
     assert_redirected_to :controller => :errors, :action => :not_found
-    assert_not issue.reload.ignored?
+    assert_not_predicate issue.reload, :ignored?
 
     # Ignore issue as moderator
     session_for(create(:moderator_user))
-    post ignore_issue_path(:id => issue)
+    post ignore_issue_path(issue)
     assert_response :redirect
     assert_predicate issue.reload, :ignored?
   end
@@ -153,23 +153,23 @@ class IssuesControllerTest < ActionDispatch::IntegrationTest
     issue = create(:issue, :reportable => target_user, :reported_user => target_user, :assigned_role => "administrator")
 
     # Ignore issue without login
-    post ignore_issue_path(:id => issue)
+    post ignore_issue_path(issue)
     assert_response :forbidden
 
     # Ignore issue as normal user
     session_for(create(:user))
-    post ignore_issue_path(:id => issue)
+    post ignore_issue_path(issue)
     assert_redirected_to :controller => :errors, :action => :forbidden
 
     # Ignore issue as moderator
     session_for(create(:moderator_user))
-    post ignore_issue_path(:id => issue)
+    post ignore_issue_path(issue)
     assert_redirected_to :controller => :errors, :action => :not_found
-    assert_not issue.reload.ignored?
+    assert_not_predicate issue.reload, :ignored?
 
     # Ignore issue as administrator
     session_for(create(:administrator_user))
-    post ignore_issue_path(:id => issue)
+    post ignore_issue_path(issue)
     assert_response :redirect
     assert_predicate issue.reload, :ignored?
   end
@@ -181,23 +181,23 @@ class IssuesControllerTest < ActionDispatch::IntegrationTest
     issue.resolve!
 
     # Reopen issue without login
-    post reopen_issue_path(:id => issue)
+    post reopen_issue_path(issue)
     assert_response :forbidden
 
     # Reopen issue as normal user
     session_for(create(:user))
-    post reopen_issue_path(:id => issue)
+    post reopen_issue_path(issue)
     assert_redirected_to :controller => :errors, :action => :forbidden
 
     # Reopen issue as administrator
     session_for(create(:administrator_user))
-    post reopen_issue_path(:id => issue)
+    post reopen_issue_path(issue)
     assert_redirected_to :controller => :errors, :action => :not_found
-    assert_not issue.reload.open?
+    assert_not_predicate issue.reload, :open?
 
     # Reopen issue as moderator
     session_for(create(:moderator_user))
-    post reopen_issue_path(:id => issue)
+    post reopen_issue_path(issue)
     assert_response :redirect
     assert_predicate issue.reload, :open?
   end
@@ -209,23 +209,23 @@ class IssuesControllerTest < ActionDispatch::IntegrationTest
     issue.resolve!
 
     # Reopen issue without login
-    post reopen_issue_path(:id => issue)
+    post reopen_issue_path(issue)
     assert_response :forbidden
 
     # Reopen issue as normal user
     session_for(create(:user))
-    post reopen_issue_path(:id => issue)
+    post reopen_issue_path(issue)
     assert_redirected_to :controller => :errors, :action => :forbidden
 
     # Reopen issue as moderator
     session_for(create(:moderator_user))
-    post reopen_issue_path(:id => issue)
+    post reopen_issue_path(issue)
     assert_redirected_to :controller => :errors, :action => :not_found
-    assert_not issue.reload.open?
+    assert_not_predicate issue.reload, :open?
 
     # Reopen issue as administrator
     session_for(create(:administrator_user))
-    post reopen_issue_path(:id => issue)
+    post reopen_issue_path(issue)
     assert_response :redirect
     assert_predicate issue.reload, :open?
   end
index dd0b1287b414c7805395a82bcccb62c0b5c773e6..2e9d79ef759e8add899921259fc241ad3f37b3de 100644 (file)
@@ -212,22 +212,9 @@ class UserBlocksControllerTest < ActionDispatch::IntegrationTest
     check_block_buttons block, :edit => 1
 
     session_for(revoker_user)
-    check_block_buttons block
-  end
-
-  private
-
-  def check_block_buttons(block, edit: 0, revoke: 0)
-    [user_blocks_path, user_block_path(block)].each do |path|
-      get path
-      assert_response :success
-      assert_select "a[href='#{edit_user_block_path block}']", :count => edit
-      assert_select "a[href='#{revoke_user_block_path block}']", :count => revoke
-    end
+    check_block_buttons block, :edit => 1
   end
 
-  public
-
   ##
   # test the new action
   def test_new
@@ -483,23 +470,32 @@ class UserBlocksControllerTest < ActionDispatch::IntegrationTest
     assert_equal "Original Reason", block.reason
 
     session_for(creator_user)
+    check_block_updates(block)
+  end
+
+  ##
+  # test the update action on revoked blocks
+  def test_update_revoked
+    creator_user = create(:moderator_user)
+    revoker_user = create(:moderator_user)
+    other_moderator_user = create(:moderator_user)
+    block = create(:user_block, :revoked, :creator => creator_user, :revoker => revoker_user, :reason => "Original Reason")
+
+    session_for(other_moderator_user)
     put user_block_path(block,
                         :user_block_period => "0",
                         :user_block => { :needs_view => false, :reason => "Updated Reason" })
-    assert_redirected_to user_block_path(block)
-    assert_equal "Block updated.", flash[:notice]
+    assert_redirected_to edit_user_block_path(block)
+    assert_equal "Only the moderators who created or revoked this block can edit it.", flash[:error]
     block.reload
-    assert_not block.active?
-    assert_equal "Updated Reason", block.reason
+    assert_not_predicate block, :active?
+    assert_equal "Original Reason", block.reason
 
-    put user_block_path(block,
-                        :user_block_period => "0",
-                        :user_block => { :needs_view => true, :reason => "Updated Reason 2" })
-    assert_redirected_to user_block_path(block)
-    assert_equal "Block updated.", flash[:notice]
-    block.reload
-    assert_predicate block, :active?
-    assert_equal "Updated Reason 2", block.reason
+    session_for(creator_user)
+    check_block_updates(block)
+
+    session_for(revoker_user)
+    check_block_updates(block)
   end
 
   ##
@@ -794,6 +790,35 @@ class UserBlocksControllerTest < ActionDispatch::IntegrationTest
 
   private
 
+  def check_block_buttons(block, edit: 0, revoke: 0)
+    [user_blocks_path, user_block_path(block)].each do |path|
+      get path
+      assert_response :success
+      assert_select "a[href='#{edit_user_block_path block}']", :count => edit
+      assert_select "a[href='#{revoke_user_block_path block}']", :count => revoke
+    end
+  end
+
+  def check_block_updates(block)
+    put user_block_path(block,
+                        :user_block_period => "0",
+                        :user_block => { :needs_view => false, :reason => "Updated Reason" })
+    assert_redirected_to user_block_path(block)
+    assert_equal "Block updated.", flash[:notice]
+    block.reload
+    assert_not_predicate block, :active?
+    assert_equal "Updated Reason", block.reason
+
+    put user_block_path(block,
+                        :user_block_period => "0",
+                        :user_block => { :needs_view => true, :reason => "Updated Reason 2" })
+    assert_redirected_to user_block_path(block)
+    assert_equal "Block updated.", flash[:notice]
+    block.reload
+    assert_predicate block, :active?
+    assert_equal "Updated Reason 2", block.reason
+  end
+
   def check_user_blocks_table(user_blocks)
     assert_dom "table#block_list tbody tr" do |rows|
       assert_equal user_blocks.count, rows.count, "unexpected number of rows in user blocks table"
index 3f862fbca752e9887cbf63df02491ea493c83f10..6a8b62f6c077217548278d3330c6c98c2823abc7 100644 (file)
@@ -1,5 +1,7 @@
 FactoryBot.define do
   factory :oauth_access_token, :class => "Doorkeeper::AccessToken" do
     application :factory => :oauth_application
+
+    resource_owner_id { create(:user).id }
   end
 end
index 8dc9e49b1180582535d0939b67fdd3ede88219be..e0b31527669d5f1d8583cdfbe65c483d58a6ec58 100644 (file)
@@ -253,26 +253,79 @@ class RichTextTest < ActiveSupport::TestCase
   def test_text_no_image
     r = RichText.new("text", "foo https://example.com/ bar")
     assert_nil r.image
+    assert_nil r.image_alt
   end
 
   def test_html_no_image
     r = RichText.new("html", "foo <a href='https://example.com/'>bar</a> baz")
     assert_nil r.image
+    assert_nil r.image_alt
   end
 
   def test_markdown_no_image
     r = RichText.new("markdown", "foo [bar](https://example.com/) baz")
     assert_nil r.image
+    assert_nil r.image_alt
   end
 
   def test_markdown_image
     r = RichText.new("markdown", "foo ![bar](https://example.com/image.jpg) baz")
     assert_equal "https://example.com/image.jpg", r.image
+    assert_equal "bar", r.image_alt
   end
 
   def test_markdown_first_image
     r = RichText.new("markdown", "foo ![bar1](https://example.com/image1.jpg) baz\nfoo ![bar2](https://example.com/image2.jpg) baz")
     assert_equal "https://example.com/image1.jpg", r.image
+    assert_equal "bar1", r.image_alt
+  end
+
+  def test_markdown_image_with_empty_src
+    r = RichText.new("markdown", "![invalid]()")
+    assert_nil r.image
+    assert_nil r.image_alt
+  end
+
+  def test_markdown_skip_image_with_empty_src
+    r = RichText.new("markdown", "![invalid]() ![valid](https://example.com/valid.gif)")
+    assert_equal "https://example.com/valid.gif", r.image
+    assert_equal "valid", r.image_alt
+  end
+
+  def test_markdown_html_image
+    r = RichText.new("markdown", "<img src='https://example.com/img_element.png' alt='alt text here'>")
+    assert_equal "https://example.com/img_element.png", r.image
+    assert_equal "alt text here", r.image_alt
+  end
+
+  def test_markdown_html_image_without_alt
+    r = RichText.new("markdown", "<img src='https://example.com/img_element.png'>")
+    assert_equal "https://example.com/img_element.png", r.image
+    assert_nil r.image_alt
+  end
+
+  def test_markdown_html_image_with_empty_src
+    r = RichText.new("markdown", "<img src='' alt='forgot src'>")
+    assert_nil r.image
+    assert_nil r.image_alt
+  end
+
+  def test_markdown_skip_html_image_with_empty_src
+    r = RichText.new("markdown", "<img src='' alt='forgot src'> <img src='https://example.com/next_img_element.png' alt='have src'>")
+    assert_equal "https://example.com/next_img_element.png", r.image
+    assert_equal "have src", r.image_alt
+  end
+
+  def test_markdown_html_image_without_src
+    r = RichText.new("markdown", "<img alt='totally forgot src'>")
+    assert_nil r.image
+    assert_nil r.image_alt
+  end
+
+  def test_markdown_skip_html_image_without_src
+    r = RichText.new("markdown", "<img alt='totally forgot src'> <img src='https://example.com/next_img_element.png' alt='have src'>")
+    assert_equal "https://example.com/next_img_element.png", r.image
+    assert_equal "have src", r.image_alt
   end
 
   private
index 25123b392f3dee63f15fd129b846674c8e584321..2a547e752aff6fa901340eee7edc619380eff06e 100644 (file)
@@ -10,39 +10,43 @@ class UserMailerTest < ActionMailer::TestCase
   def test_gpx_description_tags
     trace = create(:trace) do |t|
       create(:tracetag, :trace => t, :tag => "one")
-      create(:tracetag, :trace => t, :tag => "two")
-      create(:tracetag, :trace => t, :tag => "three")
+      create(:tracetag, :trace => t, :tag => "two&three")
+      create(:tracetag, :trace => t, :tag => "four<five")
     end
     email = UserMailer.gpx_success(trace, 100)
 
-    assert_match("<em>one</em>, <em>two</em>, <em>three</em>", email.html_part.body.to_s)
+    assert_match("<em>one</em>, <em>two&amp;three</em>, <em>four&lt;five</em>", email.html_part.body.to_s)
+    assert_match("one, two&three, four<five", email.text_part.body.to_s)
   end
 
   def test_gpx_success_all_traces_link
     trace = create(:trace)
     email = UserMailer.gpx_success(trace, 100)
-    body = Rails::Dom::Testing.html_document_fragment.parse(email.html_part.body)
-
     url = Rails.application.routes.url_helpers.url_for(:controller => "traces", :action => "mine", :host => Settings.server_url, :protocol => Settings.server_protocol)
-    assert_select body, "a[href='#{url}']"
+
+    assert_select Rails::Dom::Testing.html_document_fragment.parse(email.html_part.body),
+                  "a[href='#{url}']"
+    assert_includes email.text_part.body, url
   end
 
   def test_gpx_success_trace_link
     trace = create(:trace)
     email = UserMailer.gpx_success(trace, 100)
-    body = Rails::Dom::Testing.html_document_fragment.parse(email.html_part.body)
-
     url = Rails.application.routes.url_helpers.show_trace_url(trace.user, trace, :host => Settings.server_url, :protocol => Settings.server_protocol)
-    assert_select body, "a[href='#{url}']", :text => trace.name
+
+    assert_select Rails::Dom::Testing.html_document_fragment.parse(email.html_part.body),
+                  "a[href='#{url}']", :text => trace.name
+    assert_includes email.text_part.body, url
   end
 
   def test_gpx_failure_no_trace_link
     trace = create(:trace)
     email = UserMailer.gpx_failure(trace, "some error")
-    body = Rails::Dom::Testing.html_document_fragment.parse(email.html_part.body)
-
     url = Rails.application.routes.url_helpers.show_trace_url(trace.user, trace, :host => Settings.server_url, :protocol => Settings.server_protocol)
-    assert_select body, "a[href='#{url}']", :count => 0
+
+    assert_select Rails::Dom::Testing.html_document_fragment.parse(email.html_part.body),
+                  "a[href='#{url}']", :count => 0
+    assert_not_includes email.text_part.body, url
   end
 
   def test_html_encoding
index 92e7d419c33c50f7ec91d1899581793ffd72508a..10fd3d97ec9cb533494e72946a049def4c936620 100644 (file)
@@ -111,10 +111,10 @@ class UserTest < ActiveSupport::TestCase
     user = build(:user)
 
     user.display_name = "user_#{existing_user.id}"
-    assert_not user.valid?, "user_<id> name is valid for existing user id when it shouldn't be"
+    assert_not_predicate user, :valid?, "user_<id> name is valid for existing user id when it shouldn't be"
 
     user.display_name = "user_#{existing_user.id + 1}"
-    assert_not user.valid?, "user_<id> name is valid for new user id when it shouldn't be"
+    assert_not_predicate user, :valid?, "user_<id> name is valid for new user id when it shouldn't be"
   end
 
   def test_display_name_user_id_rename
@@ -122,7 +122,7 @@ class UserTest < ActiveSupport::TestCase
     user = create(:user)
 
     user.display_name = "user_#{existing_user.id}"
-    assert_not user.valid?, "user_<id> name is valid for existing user id when it shouldn't be"
+    assert_not_predicate user, :valid?, "user_<id> name is valid for existing user id when it shouldn't be"
 
     user.display_name = "user_#{user.id}"
     assert_predicate user, :valid?, "user_<id> name is invalid for own id, when it should be"
index df127bc8c9bb8d9acb1f032fb2810301fce4c1ae..290ff527c1c96064f6f4ca5e66c119d559efebfd 100644 (file)
--- a/yarn.lock
+++ b/yarn.lock
   resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.11.0.tgz#b0ffd0312b4a3fd2d6f77237e7248a5ad3a680ae"
   integrity sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==
 
-"@eslint/config-array@^0.17.0":
-  version "0.17.0"
-  resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.17.0.tgz#ff305e1ee618a00e6e5d0485454c8d92d94a860d"
-  integrity sha512-A68TBu6/1mHHuc5YJL0U0VVeGNiklLAL6rRmhTCP2B5XjWLMnrX+HkO+IAXyHvks5cyyY1jjK5ITPQ1HGS2EVA==
+"@eslint/config-array@^0.17.1":
+  version "0.17.1"
+  resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.17.1.tgz#d9b8b8b6b946f47388f32bedfd3adf29ca8f8910"
+  integrity sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==
   dependencies:
     "@eslint/object-schema" "^2.1.4"
     debug "^4.3.1"
     minimatch "^3.1.2"
     strip-json-comments "^3.1.1"
 
-"@eslint/js@9.7.0":
-  version "9.7.0"
-  resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.7.0.tgz#b712d802582f02b11cfdf83a85040a296afec3f0"
-  integrity sha512-ChuWDQenef8OSFnvuxv0TCVxEwmu3+hPNKvM9B34qpM0rDRbjL8t5QkQeHHeAfsKQjuH9wS82WeCi1J/owatng==
+"@eslint/js@9.8.0":
+  version "9.8.0"
+  resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.8.0.tgz#ae9bc14bb839713c5056f5018bcefa955556d3a4"
+  integrity sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==
 
 "@eslint/object-schema@^2.1.4":
   version "2.1.4"
@@ -246,15 +246,15 @@ eslint-visitor-keys@^4.0.0:
   integrity sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==
 
 eslint@^9.0.0:
-  version "9.7.0"
-  resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.7.0.tgz#bedb48e1cdc2362a0caaa106a4c6ed943e8b09e4"
-  integrity sha512-FzJ9D/0nGiCGBf8UXO/IGLTgLVzIxze1zpfA8Ton2mjLovXdAPlYDv+MQDcqj3TmrhAGYfOpz9RfR+ent0AgAw==
+  version "9.8.0"
+  resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.8.0.tgz#a4f4a090c8ea2d10864d89a6603e02ce9f649f0f"
+  integrity sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==
   dependencies:
     "@eslint-community/eslint-utils" "^4.2.0"
     "@eslint-community/regexpp" "^4.11.0"
-    "@eslint/config-array" "^0.17.0"
+    "@eslint/config-array" "^0.17.1"
     "@eslint/eslintrc" "^3.1.0"
-    "@eslint/js" "9.7.0"
+    "@eslint/js" "9.8.0"
     "@humanwhocodes/module-importer" "^1.0.1"
     "@humanwhocodes/retry" "^0.3.0"
     "@nodelib/fs.walk" "^1.2.8"
@@ -624,9 +624,9 @@ punycode@^2.1.0:
   integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
 
 qs@^6.9.4:
-  version "6.12.3"
-  resolved "https://registry.yarnpkg.com/qs/-/qs-6.12.3.tgz#e43ce03c8521b9c7fd7f1f13e514e5ca37727754"
-  integrity sha512-AWJm14H1vVaO/iNZ4/hO+HyaTehuy9nRqVdkTqlJt0HWvBiBIEXFmb4C0DGeYo3Xes9rrEW+TxHsaigCbN5ICQ==
+  version "6.13.0"
+  resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906"
+  integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==
   dependencies:
     side-channel "^1.0.6"