Merge branch 'master' into terms
authorTom Hughes <tom@compton.nu>
Fri, 7 May 2010 21:23:20 +0000 (22:23 +0100)
committerTom Hughes <tom@compton.nu>
Fri, 7 May 2010 21:23:20 +0000 (22:23 +0100)
Conflicts:
config/application.yml
lib/osm.rb
public/stylesheets/common.css

36 files changed:
app/controllers/application_controller.rb
app/controllers/changeset_controller.rb
app/controllers/diary_entry_controller.rb
app/controllers/trace_controller.rb
app/controllers/user_controller.rb
app/models/diary_entry.rb
app/models/spam_observer.rb [new file with mode: 0644]
app/models/user.rb
app/models/user_sweeper.rb
app/views/user/_user.html.erb [new file with mode: 0644]
app/views/user/list.html.erb [new file with mode: 0644]
app/views/user/suspended.html.erb [new file with mode: 0644]
app/views/user/view.html.erb
config/application.yml
config/environment.rb
config/locales/de.yml
config/locales/en.yml
config/locales/fr.yml
config/locales/hr.yml
config/locales/ia.yml
config/locales/ru.yml
config/locales/vi.yml
config/potlatch/locales/ca.yml
config/potlatch/locales/de.yml
config/potlatch/locales/gl.yml
config/potlatch/locales/hr.yml
config/potlatch/locales/ru.yml
config/routes.rb
db/migrate/050_add_user_index_to_diary_comments.rb [new file with mode: 0644]
db/migrate/051_add_status_to_user.rb [new file with mode: 0644]
lib/osm.rb
public/openlayers/OpenLayers.js
public/stylesheets/common.css
script/statistics
test/fixtures/users.yml
test/unit/user_test.rb

index 0c41170470c3d9b1054be5cb8e4c61a55e3a3b77..a53fb5374b06d02415ff8c0285590388e344398a 100644 (file)
@@ -8,7 +8,14 @@ class ApplicationController < ActionController::Base
 
   def authorize_web
     if session[:user]
-      @user = User.find(session[:user], :conditions => {:visible => true})
+      @user = User.find(session[:user], :conditions => {:status => ["active", "confirmed", "suspended"]})
+
+      if @user.status == "suspended"
+        session[:user] = nil
+        session_expires_automatically
+
+        redirect_to :controller => "user", :action => "suspended"
+      end
     elsif session[:token]
       @user = User.authenticate(:token => session[:token])
       session[:user] = @user.id
index 79000c6852598a212b79661757ee87932a1380f8..d0a357c85c8258436acbc826f8995580f3e43762 100644 (file)
@@ -255,7 +255,7 @@ class ChangesetController < ApplicationController
     conditions = conditions_nonempty
 
     if params[:display_name]
-      user = User.find_by_display_name(params[:display_name], :conditions => { :visible => true })
+      user = User.find_by_display_name(params[:display_name], :conditions => { :status => ["active", "confirmed"] })
 
       if user 
         if user.data_public? or user == @user
index 6c7c9658bd6cd73d508b14bc80ee7256fc9fb1ca..52ce742bfddf08870ae441e653e7855adb2e9458 100644 (file)
@@ -71,7 +71,7 @@ class DiaryEntryController < ApplicationController
 
   def list
     if params[:display_name]
-      @this_user = User.find_by_display_name(params[:display_name], :conditions => { :visible => true })
+      @this_user = User.find_by_display_name(params[:display_name], :conditions => { :status => ["active", "confirmed"] })
 
       if @this_user
         @title = t 'diary_entry.list.user_title', :user => @this_user.display_name
@@ -92,7 +92,7 @@ class DiaryEntryController < ApplicationController
       @title = t 'diary_entry.list.in_language_title', :language => Language.find(params[:language]).english_name
       @entry_pages, @entries = paginate(:diary_entries, :include => :user,
                                         :conditions => {
-                                          :users => { :visible => true },
+                                          :users => { :status => ["active", "confirmed"] },
                                           :visible => true,
                                           :language_code => params[:language]
                                         },
@@ -102,7 +102,7 @@ class DiaryEntryController < ApplicationController
       @title = t 'diary_entry.list.title'
       @entry_pages, @entries = paginate(:diary_entries, :include => :user,
                                         :conditions => {
-                                          :users => { :visible => true },
+                                          :users => { :status => ["active", "confirmed"] },
                                           :visible => true
                                         },
                                         :order => 'created_at DESC',
@@ -114,7 +114,7 @@ class DiaryEntryController < ApplicationController
     request.format = :rss
 
     if params[:display_name]
-      user = User.find_by_display_name(params[:display_name], :conditions => { :visible => true })
+      user = User.find_by_display_name(params[:display_name], :conditions => { :status => ["active", "confirmed"] })
 
       if user
         @entries = DiaryEntry.find(:all, 
@@ -133,7 +133,7 @@ class DiaryEntryController < ApplicationController
     elsif params[:language]
       @entries = DiaryEntry.find(:all, :include => :user,
                                  :conditions => {
-                                   :users => { :visible => true },
+                                   :users => { :status => ["active", "confirmed"] },
                                    :visible => true,
                                    :language_code => params[:language]
                                  },
@@ -145,7 +145,7 @@ class DiaryEntryController < ApplicationController
     else
       @entries = DiaryEntry.find(:all, :include => :user,
                                  :conditions => {
-                                   :users => { :visible => true },
+                                   :users => { :status => ["active", "confirmed"] },
                                    :visible => true
                                  },
                                  :order => 'created_at DESC', 
@@ -157,7 +157,7 @@ class DiaryEntryController < ApplicationController
   end
 
   def view
-    user = User.find_by_display_name(params[:display_name], :conditions => { :visible => true })
+    user = User.find_by_display_name(params[:display_name], :conditions => { :status => ["active", "confirmed"] })
 
     if user
       @entry = DiaryEntry.find(:first, :conditions => {
index 3c16b9a802722eee5f940e1b58d731376bad2cbd..f8ce29abaaa972fff209b37189daff2f623189cb 100644 (file)
@@ -27,7 +27,7 @@ class TraceController < ApplicationController
     # from display name, pick up user id if one user's traces only
     display_name = params[:display_name]
     if target_user.nil? and !display_name.blank?
-      target_user = User.find(:first, :conditions => [ "visible = ? and display_name = ?", true, display_name])
+      target_user = User.find(:first, :conditions => { :status => ["active", "confirmed"], :display_name => display_name })
       if target_user.nil?
         @title = t'trace.no_such_user.title'
         @not_found_user = display_name
index 43a6db790bc8e25375f15bf0ef57778b31d9dc0f..8fdb89b227c628c78807a87535d42c5f961edb6e 100644 (file)
@@ -11,12 +11,12 @@ class UserController < ApplicationController
   before_filter :require_allow_read_prefs, :only => [:api_details]
   before_filter :require_allow_read_gpx, :only => [:api_gpx_files]
   before_filter :require_cookies, :only => [:login, :confirm]
-  before_filter :require_administrator, :only => [:activate, :deactivate, :hide, :unhide, :delete]
-  before_filter :lookup_this_user, :only => [:activate, :deactivate, :hide, :unhide, :delete]
+  before_filter :require_administrator, :only => [:set_status, :delete, :list]
+  before_filter :lookup_this_user, :only => [:set_status, :delete]
 
   filter_parameter_logging :password, :pass_crypt, :pass_crypt_confirmation
 
-  cache_sweeper :user_sweeper, :only => [:account, :hide, :unhide, :delete]
+  cache_sweeper :user_sweeper, :only => [:account, :set_status, :delete]
 
   def terms
     @title = t 'user.new.title'
@@ -44,7 +44,7 @@ class UserController < ApplicationController
     else
       @user = User.new(params[:user])
 
-      @user.visible = true
+      @user.status = "pending"
       @user.data_public = true
       @user.description = "" if @user.description.nil?
       @user.creation_ip = request.remote_ip
@@ -89,9 +89,9 @@ class UserController < ApplicationController
         set_locale
 
         if @user.new_email.nil? or @user.new_email.empty?
-          flash.now[:notice] = t 'user.account.flash update success'
+          flash[:notice] = t 'user.account.flash update success'
         else
-          flash.now[:notice] = t 'user.account.flash update success confirm needed'
+          flash[:notice] = t 'user.account.flash update success confirm needed'
 
           begin
             Notifier.deliver_email_confirm(@user, @user.tokens.create)
@@ -99,6 +99,8 @@ class UserController < ApplicationController
             # Ignore errors sending email
           end
         end
+
+        redirect_to :action => "account", :display_name => @user.display_name
       end
     else
       if flash[:errors]
@@ -121,7 +123,7 @@ class UserController < ApplicationController
     @title = t 'user.lost_password.title'
 
     if params[:user] and params[:user][:email]
-      user = User.find_by_email(params[:user][:email], :conditions => {:visible => true})
+      user = User.find_by_email(params[:user][:email], :conditions => {:status => ["pending", "active", "confirmed"]})
 
       if user
         token = user.tokens.create
@@ -146,7 +148,7 @@ class UserController < ApplicationController
         if params[:user]
           @user.pass_crypt = params[:user][:pass_crypt]
           @user.pass_crypt_confirmation = params[:user][:pass_crypt_confirmation]
-          @user.active = true
+          @user.status = "active"
           @user.email_valid = true
 
           if @user.save
@@ -192,8 +194,10 @@ class UserController < ApplicationController
         else
           redirect_to :controller => 'site', :action => 'index'
         end
-       elsif User.authenticate(:username => email_or_display_name, :password => pass, :inactive => true)
+      elsif User.authenticate(:username => email_or_display_name, :password => pass, :pending => true)
         flash.now[:error] = t 'user.login.account not active'
+      elsif User.authenticate(:username => email_or_display_name, :password => pass, :suspended => true)
+        flash.now[:error] = t 'user.login.account suspended'
       else
         flash.now[:error] = t 'user.login.auth failure'
       end
@@ -226,7 +230,7 @@ class UserController < ApplicationController
       token = UserToken.find_by_token(params[:confirm_string])
       if token and !token.user.active?
         @user = token.user
-        @user.active = true
+        @user.status = "active"
         @user.email_valid = true
         @user.save!
         referer = token.referer
@@ -251,7 +255,6 @@ class UserController < ApplicationController
         @user = token.user
         @user.email = @user.new_email
         @user.new_email = nil
-        @user.active = true
         @user.email_valid = true
         if @user.save
           flash[:notice] = t 'user.confirm_email.success'
@@ -291,7 +294,7 @@ class UserController < ApplicationController
   def make_friend
     if params[:display_name]
       name = params[:display_name]
-      new_friend = User.find_by_display_name(name, :conditions => {:visible => true})
+      new_friend = User.find_by_display_name(name, :conditions => {:status => ["active", "confirmed"]})
       friend = Friend.new
       friend.user_id = @user.id
       friend.friend_user_id = new_friend.id
@@ -317,7 +320,7 @@ class UserController < ApplicationController
   def remove_friend
     if params[:display_name]
       name = params[:display_name]
-      friend = User.find_by_display_name(name, :conditions => {:visible => true})
+      friend = User.find_by_display_name(name, :conditions => {:status => ["active", "confirmed"]})
       if @user.is_friends_with?(friend)
         Friend.delete_all "user_id = #{@user.id} AND friend_user_id = #{friend.id}"
         flash[:notice] = t 'user.remove_friend.success', :name => friend.display_name
@@ -334,47 +337,57 @@ class UserController < ApplicationController
   end
 
   ##
-  # activate a user, allowing them to log in
-  def activate
-    @this_user.update_attributes(:active => true)
+  # sets a user's status
+  def set_status
+    @this_user.update_attributes(:status => params[:status])
     redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
   end
 
   ##
-  # deactivate a user, preventing them from logging in
-  def deactivate
-    @this_user.update_attributes(:active => false)
+  # delete a user, marking them as deleted and removing personal data
+  def delete
+    @this_user.delete
     redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
   end
 
   ##
-  # hide a user, marking them as logically deleted
-  def hide
-    @this_user.update_attributes(:visible => false)
-    redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
-  end
+  # display a list of users matching specified criteria
+  def list
+    if request.post?
+      ids = params[:user].keys.collect { |id| id.to_i }
 
-  ##
-  # unhide a user, clearing the logically deleted flag
-  def unhide
-    @this_user.update_attributes(:visible => true)
-    redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
-  end
+      User.update_all("status = 'confirmed'", :id => ids) if params[:confirm]
+      User.update_all("status = 'deleted'", :id => ids) if params[:hide]
 
-  ##
-  # delete a user, marking them as deleted and removing personal data
-  def delete
-    @this_user.delete
-    redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
+      redirect_to url_for(:status => params[:status], :ip => params[:ip], :page => params[:page])
+    else
+      conditions = Hash.new
+      conditions[:status] = params[:status] if params[:status]
+      conditions[:creation_ip] = params[:ip] if params[:ip]
+
+      @user_pages, @users = paginate(:users,
+                                     :conditions => conditions,
+                                     :order => :id,
+                                     :per_page => 50)
+    end
   end
+
 private
+
   ##
   # require that the user is a administrator, or fill out a helpful error message
   # and return them to the user page.
   def require_administrator
-    unless @user.administrator?
+    if @user and not @user.administrator?
       flash[:error] = t('user.filter.not_an_administrator')
-      redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
+
+      if params[:display_name]
+        redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
+      else
+        redirect_to :controller => 'user', :action => 'login', :referer => request.request_uri
+      end
+    elsif not @user
+      redirect_to :controller => 'user', :action => 'login', :referer => request.request_uri
     end
   end
 
index 0524b75cf3a0616938da05ce8a27531fabb3b30b..9146eb800bed9347e3ff5e79007295a269b603f6 100644 (file)
@@ -8,7 +8,7 @@ class DiaryEntry < ActiveRecord::Base
   has_many :visible_comments, :class_name => "DiaryComment",
                               :include => :user,
                               :conditions => {
-                                :users => { :visible => true },
+                                :users => { :status => ["active", "confirmed" ] },
                                 :visible => true
                               },
                               :order => "diary_comments.id"
diff --git a/app/models/spam_observer.rb b/app/models/spam_observer.rb
new file mode 100644 (file)
index 0000000..21561f6
--- /dev/null
@@ -0,0 +1,15 @@
+class SpamObserver < ActiveRecord::Observer
+  observe User, DiaryEntry, DiaryComment
+
+  def after_save(record)
+    case
+    when record.is_a?(User): user = record
+    when record.is_a?(DiaryEntry): user = record.user
+    when record.is_a?(DiaryComment): user = record.user
+    end
+
+    if user.status == "active" and user.spam_score > APP_CONFIG['spam_threshold']
+      user.update_attributes(:status => "suspended")
+    end
+  end
+end
index f02c9a5cd0067b63afc3984575534c38fb0a550b..31b0f27a03428ef9223b3c00bfe05bd89504c27f 100644 (file)
@@ -3,10 +3,11 @@ class User < ActiveRecord::Base
 
   has_many :traces, :conditions => { :visible => true }
   has_many :diary_entries, :order => 'created_at DESC'
+  has_many :diary_comments, :order => 'created_at DESC'
   has_many :messages, :foreign_key => :to_user_id, :conditions => { :to_user_visible => true }, :order => 'sent_on DESC'
   has_many :new_messages, :class_name => "Message", :foreign_key => :to_user_id, :conditions => { :to_user_visible => true, :message_read => false }, :order => 'sent_on DESC'
   has_many :sent_messages, :class_name => "Message", :foreign_key => :from_user_id, :conditions => { :from_user_visible => true }, :order => 'sent_on DESC'
-  has_many :friends, :include => :befriendee, :conditions => ["users.visible = ?", true]
+  has_many :friends, :include => :befriendee, :conditions => "users.status IN ('active', 'confirmed')"
   has_many :tokens, :class_name => "UserToken"
   has_many :preferences, :class_name => "UserPreference"
   has_many :changesets
@@ -55,8 +56,11 @@ class User < ActiveRecord::Base
       user = token.user if token
     end
 
-    if user
-      user = nil unless user.visible? and (user.active? or options[:inactive])
+    if user and
+      ( user.status == "deleted" or
+        ( user.status == "pending" and not options[:pending] ) or
+        ( user.status == "suspended" and not options[:suspended] ) )
+      user = nil
     end
 
     token.update_attribute(:expiry, 1.week.from_now) if token and user
@@ -106,7 +110,8 @@ class User < ActiveRecord::Base
       bounds = gc.bounds(radius)
       sql_for_distance = gc.sql_for_distance("home_lat", "home_lon")
       nearby = User.find(:all, 
-                         :conditions => ["id != ? AND visible = ? AND data_public = ? AND #{sql_for_distance} <= ?", id, true, true, radius], :order => sql_for_distance, :limit => num)
+                         :conditions => ["id != ? AND status IN (\'active\', \'confirmed\') AND data_public = ? AND #{sql_for_distance} <= ?", id, true, radius],
+                         :order => sql_for_distance, :limit => num)
     else
       nearby = []
     end
@@ -128,6 +133,18 @@ class User < ActiveRecord::Base
     return false
   end
 
+  ##
+  # returns true if a user is visible
+  def visible?
+    ["pending","active","confirmed"].include? self.status
+  end
+
+  ##
+  # returns true if a user is active
+  def active?
+    ["active","confirmed"].include? self.status
+  end
+
   ##
   # returns true if the user has the moderator role, false otherwise
   def moderator?
@@ -153,8 +170,9 @@ class User < ActiveRecord::Base
     active_blocks.detect { |b| b.needs_view? }
   end
 
+  ##
+  # delete a user - leave the account but purge most personal data
   def delete
-    self.active = false
     self.display_name = "user_#{self.id}"
     self.description = ""
     self.home_lat = nil
@@ -162,8 +180,24 @@ class User < ActiveRecord::Base
     self.image = nil
     self.email_valid = false
     self.new_email = nil
-    self.visible = false
+    self.status = "deleted"
     self.save
   end
 
+  ##
+  # return a spam score for a user
+  def spam_score
+    changeset_score = self.changesets.find(:all, :limit => 10).length * 50
+    trace_score = self.traces.find(:all, :limit => 10).length * 50
+    diary_entry_score = self.diary_entries.inject(0) { |s,e| s += OSM.spam_score(e.body) }
+    diary_comment_score = self.diary_comments.inject(0) { |s,e| s += OSM.spam_score(e.body) }
+
+    score = OSM.spam_score(self.description) * 2
+    score += diary_entry_score / self.diary_entries.length if self.diary_entries.length > 0
+    score += diary_comment_score / self.diary_comments.length if self.diary_comments.length > 0
+    score -= changeset_score
+    score -= trace_score
+
+    return score.to_i
+  end
 end
index 7f172317d4adc0fc7d5e67efeccdb9581667a0e2..d2fd983f76221d56215eab4c315763ffda02e374 100644 (file)
@@ -14,7 +14,7 @@ private
   def expire_cache_for(old_record, new_record)
     if old_record and
         (new_record.nil? or
-         old_record.visible != new_record.visible or
+         old_record.visible? != new_record.visible? or
          old_record.display_name != new_record.display_name)
       old_record.diary_entries.each do |entry|
         expire_action(:controller => 'diary_entry', :action => 'view', :display_name => old_record.display_name, :id => entry.id)
diff --git a/app/views/user/_user.html.erb b/app/views/user/_user.html.erb
new file mode 100644 (file)
index 0000000..bbc89f9
--- /dev/null
@@ -0,0 +1,27 @@
+<% cl = cycle('table0', 'table1') %>
+
+<tr class="<%= cl %>">
+  <td>
+    <%= user_thumbnail(user) %>
+  </td>
+  <td>
+    <p>
+      <% if user.creation_ip %>
+        <%= t 'user.list.summary',
+            :name => link_to(h(user.display_name), :action => "view", :display_name => user.display_name),
+            :ip_address => link_to(user.creation_ip, :ip => user.creation_ip),
+            :date => l(user.creation_time, :format => :friendly)
+        %>
+      <% else %>
+        <%= t 'user.list.summary_no_ip',
+            :name => link_to(h(user.display_name), :action => "view", :display_name => user.display_name),
+            :date => l(user.creation_time, :format => :friendly)
+        %>
+      <% end %>
+    </p>
+    <%= htmlize(user.description) %>
+  </td>
+  <td>
+    <%= check_box_tag "user_#{user.id}", "", false, :name => "user[#{user.id}]" %>
+  </td>
+</tr>
diff --git a/app/views/user/list.html.erb b/app/views/user/list.html.erb
new file mode 100644 (file)
index 0000000..fac7c44
--- /dev/null
@@ -0,0 +1,44 @@
+<% @title = t('user.list.title') %>
+
+<h1><%= t('user.list.heading') %></h1>
+
+<% unless @users.empty? %>
+  <% form_tag do %>
+    <%= hidden_field_tag :status, params[:status] if params[:status] %>
+    <%= hidden_field_tag :ip, params[:ip] if params[:ip] %>
+    <%= hidden_field_tag :page, params[:page] if params[:page] %>
+    <table id="user_list">
+      <tr>
+        <td colspan="2">
+          <%= t 'user.list.showing',
+              :page => @user_pages.current_page.number,
+              :first_item => @user_pages.current_page.first_item,
+              :last_item => @user_pages.current_page.last_item,
+              :items => @user_pages.item_count,
+              :count => @user_pages.current_page.last_item - @user_pages.current_page.first_item + 1
+          %>
+          <% if @user_pages.page_count > 1 %>
+          | <%= pagination_links_each(@user_pages, {}) { |n| link_to n, params.merge(:page => n) } %>
+          <% end %>
+        </td>
+        <td>
+          <%=
+            check_box_tag("user_all", "1", false, :onchange => update_page do |page|
+              @users.each do |user|
+                page << "$('user_#{user.id}').checked = $('user_all').checked;"
+              end
+            end)
+          %>
+        </td>
+      </tr>
+      <%= render :partial => 'user', :collection => @users %>
+    </table>
+
+    <div id="user_list_actions">
+      <%= submit_tag t('user.list.confirm'), :name => "confirm" %>
+      <%= submit_tag t('user.list.hide'), :name => "hide" %>
+    </div>
+  <% end %>
+<% else %>
+  <p><%= t "user.list.empty" %></p>
+<% end %>
diff --git a/app/views/user/suspended.html.erb b/app/views/user/suspended.html.erb
new file mode 100644 (file)
index 0000000..27b8dc3
--- /dev/null
@@ -0,0 +1,5 @@
+<% @title = t "user.suspended.title" %>
+
+<h1><%= t "user.suspended.heading" %></h1>
+
+<%= t "user.suspended.body", :webmaster => "webmaster@openstreetmap.org" %>
index b333b5c67eef1bb5638b4af34f4045b23e24a49c..2aca75f5322f26f75167ed1052b7f6d2b10473b3 100644 (file)
   <% end %>
   <% if @user and @user.administrator? %>
     <br/>
-    <% if @this_user.active? %>
-      <%= link_to t('user.view.deactivate_user'), {:controller => 'user', :action => 'deactivate', :display_name => @this_user.display_name}, {:confirm => t('user.view.confirm')} %>
-    <% else %>
-      <%= link_to t('user.view.activate_user'), {:controller => 'user', :action => 'activate', :display_name => @this_user.display_name}, {:confirm => t('user.view.confirm')} %>
+    <% if ["active", "confirmed"].include? @this_user.status %>
+      <%= link_to t('user.view.deactivate_user'), {:controller => 'user', :action => 'set_status', :status => 'pending', :display_name => @this_user.display_name}, {:confirm => t('user.view.confirm')} %> |
+    <% elsif ["pending"].include? @this_user.status %>
+      <%= link_to t('user.view.activate_user'), {:controller => 'user', :action => 'set_status', :status => 'active', :display_name => @this_user.display_name}, {:confirm => t('user.view.confirm')} %> |
     <% end %>
-    |
-    <% if @this_user.visible? %>
-      <%= link_to t('user.view.hide_user'), {:controller => 'user', :action => 'hide', :display_name => @this_user.display_name}, {:confirm => t('user.view.confirm')} %>
-      |
-      <%= link_to t('user.view.delete_user'), {:controller => 'user', :action => 'delete', :display_name => @this_user.display_name}, {:confirm => t('user.view.confirm')} %>
+    <% if ["active", "suspended"].include? @this_user.status %>
+      <%= link_to t('user.view.confirm_user'), {:controller => 'user', :action => 'set_status', :status => 'confirmed', :display_name => @this_user.display_name}, {:confirm => t('user.view.confirm')} %> |
+    <% end %>
+    <% if ["pending", "active", "confirmed", "suspended"].include? @this_user.status %>
+      <%= link_to t('user.view.hide_user'), {:controller => 'user', :action => 'set_status', :status => 'deleted', :display_name => @this_user.display_name}, {:confirm => t('user.view.confirm')} %> |
     <% else %>
-      <%= link_to t('user.view.unhide_user'), {:controller => 'user', :action => 'unhide', :display_name => @this_user.display_name}, {:confirm => t('user.view.confirm')} %>
+      <%= link_to t('user.view.unhide_user'), {:controller => 'user', :action => 'set_status', :status => 'active', :display_name => @this_user.display_name}, {:confirm => t('user.view.confirm')} %> |
     <% end %>
+    <%= link_to t('user.view.delete_user'), {:controller => 'user', :action => 'delete', :display_name => @this_user.display_name}, {:confirm => t('user.view.confirm')} %>
   <% end %>
 </div>
 
@@ -80,6 +81,8 @@
 <% if @user and @user.administrator? %>
   <p><b><%= t 'user.view.email address' %></b> <%= @this_user.email %></p>  
   <p><b><%= t 'user.view.created from' %></b> <%= @this_user.creation_ip %></p>
+  <p><b><%= t 'user.view.status' %></b> <%= @this_user.status.capitalize %></p>
+  <p><b><%= t 'user.view.spam score' %></b> <%= @this_user.spam_score %></p>
 <% end %>
 
 <h3><%= t 'user.view.description' %></h3>
index 7b2c603f087ae364e24123293dd238442caa0c6f..d405709657166f85a59903e359d1da4269dbc199 100644 (file)
@@ -22,6 +22,8 @@ standard_settings: &standard_settings
   # Quova authentication details
   #quova_username: ""
   #quova_password: ""
+  # Spam threshold
+  spam_threshold: 50
   # Default legale (jurisdiction location) for contributor terms
   default_legale: GB
  
index d9ffcc965bdd83e51cd740c3246b403df9eb0d65..93b6e86d2a16415409fd5b0f116a0c3e7a670491 100644 (file)
@@ -100,7 +100,7 @@ Rails::Initializer.run do |config|
   config.active_record.schema_format = :sql
 
   # Activate observers that should always be running
-  # config.active_record.observers = :cacher, :garbage_collector
+  config.active_record.observers = :spam_observer
 
   # Make Active Record use UTC-base instead of local time
   config.active_record.default_timezone = :utc
index 348091964bc96c4fa4bf199fafbd27eda9c510eb..417d53eecf82c537fcf02033d4ae871b13d38317 100644 (file)
@@ -885,7 +885,7 @@ de:
       history_tooltip: Änderungen für diesen Bereich anzeigen
       history_zoom_alert: Du musst näher heranzoomen, um die Chronik zu sehen
   layouts: 
-    copyright: Urheberrechtsinformation + Lizenz
+    copyright: Urheberrecht + Lizenz
     donate: Unterstütze die OpenStreetMap-Hardwarespendenaktion durch eine eigene {{link}}.
     donate_link_text: Spende
     edit: Bearbeiten
@@ -919,7 +919,7 @@ de:
     make_a_donation: 
       text: Spenden
       title: Unterstütze OpenStreetMap mit einer Geldspende
-    news_blog: News-Blog
+    news_blog: Neuigkeiten-Blog
     news_blog_tooltip: News-Blog über OpenStreetMap, freie geographische Daten, etc.
     osm_offline: Die OpenStreetMap-Datenbank ist im Moment wegen wichtiger Wartungsarbeiten nicht verfügbar.
     osm_read_only: Die OpenStreetMap-Datenbank ist im Moment wegen wichtiger Wartungsarbeiten im „Nur-Lesen-Modus“.
@@ -937,14 +937,14 @@ de:
     welcome_user_link_tooltip: Eigene Benutzerseite
   license_page: 
     foreign: 
-      english_link: das englischsprachige Original
-      text: Für den Fall einer Abweichung zwischen der vorliegenden Übersetzung und {{english_original_link}}, ist die englischsprachige Seite maßgebend
+      english_link: dem englischsprachigen Original
+      text: Für den Fall einer Abweichung zwischen der vorliegenden Übersetzung und {{english_original_link}}, ist die englischsprachige Seite maßgebend.
       title: Über diese Übersetzung
-    legal_babble: "<h2>Urheberrechtsinformation und Lizenz</h2>\n\n<p>\n  OpenStreetMap besteht aus <i>freien Daten</i>, die gemäß der Lizenz <a href=\"http://creativecommons.org/licenses/by-sa/2.0/\">Creative Commons Attribution-ShareAlike 2.0</a> (CC-BY-SA) verfügbar sind.\n</p>\n<p>\n  Es steht Dir frei unsere Daten und Karten zu kopieren, weiterzugeben, zu übermittelt sowie anzupassen, sofern Du OpenStreetMap und die daran Mitwirkenden angibst. Für den Fall, dass Du auf Basis unsere Daten und Karten Veränderungen vornimmst oder als Basis für weitere Bearbeitungen verwendest, kannst Du das Ergebnis auch nur gemäß der selben Lizenz weitergeben. Der vollständige Lizenztext ist unter <a href=\"http://creativecommons.org/licenses/by-sa/2.0/legalcode\">Lizenz</a> einsehbar und erläutert Deine Rechte und Pflichten.\n</p>\n\n<h3>So ist auf die Urheberschaft von OpenStreetMap hinzuweisen</h3>\n<p>\n  Sofern Du Bilder von OpenStreetMap verwendest, so ist mindestens &bdquo;&copy; OpenStreetMap und Mitwirkende, CC-BY-SA&ldquo; anzugeben. Werden hingegen ausschließlich Geodaten genutzt, so ist mindestens &bdquo;Geodaten &copy; OpenStreetMap und Mitwirkende, CC-BY-SA&ldquo; anzugeben.\n</p>\n<p>\n  Wo möglich muss ein Hyperlink auf OpenStreetMap <a href=\"http://www.openstreetmap.org/\">http://www.openstreetmap.org/</a> und die Lizenz CC-BY-SA <a   href=\"http://creativecommons.org/licenses/by-sa/2.0/\">http://creativecommons.org/licenses/by-sa/2.0/</a> gesetzt werden. Für den Fall, dass Du ein Medium einsetzt, bei dem keine derartigen Verweise möglich sind (z. B. ein gedrucktes Buch), schlagen wir vor, dass Du Deine Leser auf www.openstreetmap.org und www.creativecommons.org verweist.\n</p>\n\n<h3>Mehr hierzu in Erfahrung bringen</h3>\n<p>\n  Mehr dazu, wie unsere Daten verwendet werden können ist unter <a href=\"http://wiki.openstreetmap.org/wiki/Legal_FAQ\">Häufige rechtliche Fragen</a> nachzulesen.\n</p>\n<p>\n  Die Bearbeiter von OpenStreetMap möchten wird darauf hinweisen, dass Sie keinesfalls Daten aus urheberrechtlich geschützten Quellen verwenden dürfen (z. B. Google Maps oder gedruckte Kartenwerke) ohne vorher die ausdrückliche Erlaubnis des Rechteinhabers erhalten zu haben.\n</p>\n<p>\n  Obzwar OpenStreetMap aus freien Daten besteht, können wir Dritten keine kostenfreie Programmierschnittstelle (API) für Karten bereitstellen.\n  \n  Siehe hierzu die <a href=\"http://wiki.openstreetmap.org/wiki/API_usage_policy\">Richtlinie zur Nutzung einer API</a>, die <a href=\"http://wiki.openstreetmap.org/wiki/Tile_usage_policy\">Richtlinie zur Nutzung von Kachelgrafiken</a> und die <a href=\"http://wiki.openstreetmap.org/wiki/Nominatim#Usage_Policy\">Nutzungsrichtlinie bezüglich Daten von Nominatim</a>.\n</p>\n\n<h3>Unsere Mitwirkenden</h3>\n<p>\n  Die von uns verwendete Lizenz CC-BY-SA verlangt, dass Du &bdquo;für das betreffende Medium oder Mittel angemessen, auf die ursprünglichen Bearbeiter hinweist.&ldquo; Einige an OpenStreetMap Mitwirkende verlangen keine über den Vermerk &bdquo;OpenStreetMap und Mitwirkende&ldquo; hinausgehende Hinweise. Wo allerdings Daten von Nationalen Kartografierungsinstitutionen oder aus anderen umfangreichen Quellen einbezogen wurden, ist es sinnvoll, deren Lizenzhinweise direkt wiederzugeben oder auf Sie auf dieser Website zu verlinken.\n</p>\n\n<ul id=\"contributors\">\n   <li><strong>Australien</strong>: Enthält Daten zu Siedlungen, die auf Daten des Australian Bureau of Statistics basieren.</li>\n   <li><strong>Kanada</strong>: Enthält Daten von GeoBase&reg;, GeoGratis (&copy; Department of Natural Resources Canada), CanVec (&copy; Department of Natural Resources Canada) und StatCan (Geography Division, Statistics Canada).</li>\n   <li><strong>Neuseeland</strong>: Enthält Daten aus Land Information New Zealand. Urheberrecht vorbehalten.</li>\n   <li><strong>Vereinigtes Königreich</strong>: Enthält Daten des Ordnance Survey &copy; Urheber- und Datenbankrecht 2010.</li>\n</ul>\n\n<p>\n  Die Einbeziehung von Daten bei OpenStreetMap impliziert nicht, das der ursprüngliche Datenlieferant OpenStreetMap unterstützt, Gewährleistung gibt noch Haftung übernimmt.\n</p>"
+    legal_babble: "<h2>Urheberrecht und Lizenz</h2>\n\n<p>\n  OpenStreetMap besteht aus <i>freien Daten</i>, die gemäß der Lizenz <a href=\"http://creativecommons.org/licenses/by-sa/2.0/\">Creative Commons Attribution-ShareAlike 2.0</a> (CC-BY-SA) verfügbar sind.\n</p>\n<p>\n  Es steht Dir frei unsere Daten und Karten zu kopieren, weiterzugeben, zu übermittelt sowie anzupassen, sofern Du OpenStreetMap und die Mitwirkenden als Quelle angibst. Für den Fall, dass Du auf Basis unserer Daten und Karten Anpassungen vornimmst, oder sie als Basis für weitere Bearbeitungen verwendest, kannst Du das Ergebnis auch nur gemäß der selben Lizenz weitergeben. Der vollständige Lizenztext ist unter <a href=\"http://creativecommons.org/licenses/by-sa/2.0/legalcode\">Lizenz</a> einsehbar und erläutert Deine Rechte und Pflichten.\n</p>\n\n<h3>So ist auf die Urheberschaft von OpenStreetMap hinzuweisen</h3>\n<p>\n  Sofern Du Bilder von OpenStreetMap verwendest, so ist mindestens &bdquo;&copy; OpenStreetMap und Mitwirkende, CC-BY-SA&ldquo; als Quelle anzugeben. Werden hingegen ausschließlich Geodaten genutzt, so ist mindestens &bdquo;Geodaten &copy; OpenStreetMap und Mitwirkende, CC-BY-SA&ldquo; anzugeben.\n</p>\n<p>\n  Wo möglich, muss ein Hyperlink auf OpenStreetMap <a href=\"http://www.openstreetmap.org/\">http://www.openstreetmap.org/</a> und die Lizenz CC-BY-SA <a   href=\"http://creativecommons.org/licenses/by-sa/2.0/\">http://creativecommons.org/licenses/by-sa/2.0/</a> gesetzt werden. Für den Fall, dass Du ein Medium einsetzt, bei dem keine derartigen Verweise möglich sind (z. B. ein gedrucktes Buch), schlagen wir vor, dass Du Deine Leser auf www.openstreetmap.org und www.creativecommons.org hinweist.\n</p>\n\n<h3>Mehr hierzu in Erfahrung bringen</h3>\n<p>\n  Mehr dazu, wie unsere Daten verwendet werden können, ist unter <a href=\"http://wiki.openstreetmap.org/wiki/Legal_FAQ\">Häufige rechtliche Fragen</a> nachzulesen.\n</p>\n<p>\n  Die Mitwirkenden von OpenStreetMap weisen wir darauf hin, dass Sie keinesfalls Daten aus urheberrechtlich geschützten Quellen verwenden dürfen (z. B. Google Maps oder gedruckte Kartenwerke), ohne vorher die ausdrückliche Erlaubnis des Rechteinhabers erhalten zu haben.\n</p>\n<p>\n  Obzwar OpenStreetMap aus freien Daten besteht, können wir Dritten keine kostenfreie Programmierschnittstelle (API) für Karten bereitstellen.\n  \n  Siehe hierzu die <a href=\"http://wiki.openstreetmap.org/wiki/API_usage_policy\">Richtlinie zur Nutzung einer API</a>, die <a href=\"http://wiki.openstreetmap.org/wiki/Tile_usage_policy\">Richtlinie zur Nutzung von Kachelgrafiken</a> und die <a href=\"http://wiki.openstreetmap.org/wiki/Nominatim#Usage_Policy\">Nutzungsrichtlinie bezüglich Daten von Nominatim</a>.\n</p>\n\n<h3>Unsere Mitwirkenden</h3>\n<p>\n  Die von uns verwendete Lizenz CC-BY-SA verlangt, dass Du &bdquo;für das betreffende Medium oder Mittel in angemessener Weise, auf die ursprünglichen Bearbeiter hinweist.&ldquo; Einige an OpenStreetMap Mitwirkende verlangen keine über den Vermerk &bdquo;OpenStreetMap und Mitwirkende&ldquo; hinausgehende Hinweise. Wo allerdings Daten von nationalen Kartografierungsinstitutionen oder aus anderen umfangreichen Quellen einbezogen wurden, ist es sinnvoll, deren Lizenzhinweise direkt wiederzugeben oder auf diese auf dieser Website zu verlinken.\n</p>\n\n<ul id=\"contributors\">\n   <li><strong>Australien</strong>: Enthält Daten zu Siedlungen, die auf Daten des Australian Bureau of Statistics basieren.</li>\n   <li><strong>Kanada</strong>: Enthält Daten von GeoBase&reg;, GeoGratis (&copy; Department of Natural Resources Canada), CanVec (&copy; Department of Natural Resources Canada) und StatCan (Geography Division, Statistics Canada).</li>\n   <li><strong>Neuseeland</strong>: Enthält Daten aus Land Information New Zealand. Urheberrecht vorbehalten.</li>\n   <li><strong>Vereinigtes Königreich</strong>: Enthält Daten des Ordnance Survey &copy; Urheber- und Datenbankrecht 2010.</li>\n</ul>\n\n<p>\n  Die Einbeziehung von Daten bei OpenStreetMap impliziert nicht, das der ursprüngliche Datenlieferant OpenStreetMap unterstützt, Gewährleistung gibt, noch Haftung übernimmt.\n</p>"
     native: 
       mapping_link: mit dem Kartieren anfangen
-      native_link: THIS_LANGUAGE_NAME_HERE Sprachversion
-      text: Du befindest dich auf der Seite mit der englischsprachigen Version der Urheberrechtsinformationen. Du kannst zur {{native_link}} dieser Seite zurückkehren oder das Lesen der Urheberrechtsinformationen beenden und {{mapping_link}}.
+      native_link: deutschen Sprachversion
+      text: Du befindest Dich auf der Seite mit der englischsprachigen Version der Urheberrechts- und Lizensierungsinformationen. Du kannst zur {{native_link}} dieser Seite zurückkehren oder das Lesen der Urheberrechtsinformationen beenden und {{mapping_link}}.
       title: Über diese Seite
   message: 
     delete: 
index 3b83dece8140e1bb3427c252d9251d8561324e2f..5abae7222ec5b3617d17e3ab10790e243ffa3af3 100644 (file)
@@ -1489,6 +1489,7 @@ en:
       lost password link: "Lost your password?"
       login_button: "Login"
       account not active: "Sorry, your account is not active yet.<br />Please click on the link in the account confirmation email to activate your account."
+      account suspended: Sorry, your account has been suspended due to suspicious activity.<br />Please contact the <a href="mailto:webmaster@openstreetmap.org">webmaster</a> if you wish to discuss this.
       auth failure: "Sorry, could not log in with those details."
     logout:
       title: "Logout"
@@ -1564,6 +1565,8 @@ en:
       ago: "({{time_in_words_ago}} ago)"
       email address: "Email address:"
       created from: "Created from:"
+      status: "Status:"
+      spam score: "Spam Score:"
       description: Description
       user location: User location
       if set location: "If you set your location, a pretty map and stuff will appear here. You can set your home location on your {{settings_link}} page."
@@ -1588,6 +1591,7 @@ en:
       create_block: "block this user"
       activate_user: "activate this user"
       deactivate_user: "deactivate this user"
+      confirm_user: "confirm this user"
       hide_user: "hide this user"
       unhide_user: "unhide this user"
       delete_user: "delete this user"
@@ -1655,6 +1659,30 @@ en:
       not_a_friend: "{{name}} is not one of your friends."
     filter:
       not_an_administrator: "You need to be an administrator to perform that action."
+    list:
+      title: Users
+      heading: Users
+      showing:
+        one: Showing page {{page}} ({{first_item}} of {{items}})
+        other: Showing page {{page}} ({{first_item}}-{{last_item}} of {{items}})
+      summary: "{{name}} created from {{ip_address}} on {{date}}"
+      summary_no_ip: "{{name}} created on {{date}}"
+      confirm: Confirm Selected Users
+      hide: Hide Selected Users
+      empty: No matching users found
+    suspended:
+      title: Account Suspended
+      heading: Account Suspended
+      body: |
+        <p>
+          Sorry, your account has been automatically suspended due to
+          suspicious activity.
+        </p>
+        <p>
+          This decision will be reviewed by an administrator shortly, or
+          you may contact the <a href="mailto:{{webmaster}}">webmaster</a> if
+          you wish to discuss this.
+        </p>
   user_role:
     filter:
       not_an_administrator: "Only administrators can perform user role management, and you are not an administrator."
index e4e217c8f898d1a5508963a6880b10b250a8e91e..c7347646be08589be0e6e2a29bab2f10c659e353 100644 (file)
@@ -129,7 +129,13 @@ fr:
     navigation: 
       all: 
         next_changeset_tooltip: Groupe de modifications suivant
+        next_node_tooltip: Nœud suivant
+        next_relation_tooltip: Relation suivante
+        next_way_tooltip: Way suivant
         prev_changeset_tooltip: Groupe de modifications précédent
+        prev_node_tooltip: Nœud précédent
+        prev_relation_tooltip: Relation précédente
+        prev_way_tooltip: Way précédent
       user: 
         name_changeset_tooltip: Voir les modifications par {{user}}
         next_changeset_tooltip: Modifications suivantes par {{user}}
@@ -218,6 +224,10 @@ fr:
       zoom_or_select: Zoomer ou sélectionner une zone de la carte pour la visualiser
     tag_details: 
       tags: "Balises :"
+      wiki_link: 
+        key: La description du tag {{key}} sur le wiki
+        tag: La description du tag {{key}}={{value}} sur le wiki
+      wikipedia_link: L'article {{page}} sur Wikipedia
     timeout: 
       sorry: Désolé, les données pour le type {{type}} avec l'id {{id}} prennent trop de temps à être récupérées.
       type: 
@@ -866,6 +876,7 @@ fr:
       history_tooltip: Voir les modifications dans cette zone
       history_zoom_alert: Vous devez zoomer pour voir l’historique des modifications
   layouts: 
+    copyright: Copyright &amp; Licence
     donate: Soutenez OpenStreetMap, {{link}} au fond pour améliorer le matériel.
     donate_link_text: participez
     edit: Modifier
@@ -914,6 +925,17 @@ fr:
     view_tooltip: Afficher la carte
     welcome_user: Bienvenue, {{user_link}}
     welcome_user_link_tooltip: Votre page utilisateur
+  license_page: 
+    foreign: 
+      english_link: original en anglais
+      text: En cas de conflit entre cette page et la page {{english_original_link}}, la version anglaise prime
+      title: A propos de cette traduction
+    legal_babble: "<h2>Copyright et licence</h2>\n<p>\n   OpenStreetMap est un ensemble de <i>données ouvertes</i>, disponibles sous la licence <a\n   href=\"http://creativecommons.org/licenses/by-sa/2.0/\">Creative\n   Commons Attribution-ShareAlike 2.0</a> (CC-BY-SA).\n</p>\n<p>\n  Vous êtes libre de copier, distribuer, transmettre et adapter nos cartes\n  et données, à condition que vous créditiez OpenStreetMap et ses\n  contributeurs. Si vous modifiez ou utilisez nos cartes ou données dans d'autres travaux,\n  vous ne pouvez distribuer ceux-ci que sous la même licence. Le\n  <a href=\"http://creativecommons.org/licenses/by-sa/2.0/legalcode\">texte\n  légal complet</a> détaille vos droits et responsabilités.\n</p>\n\n<h3>Comment créditer OpenStreetMap</h3>\n<p>\n  Si vous utilisez les images d'OpenStreetMap, nous demandons que votre\n  crédit comporte au moins la mention &ldquo;&copy; les contributeurs d'OpenStreetMap\n  CC-BY-SA&rdquo;. Si vous n'utilisez que les données des cartes,\n  nous demandons &ldquo;Données de la carte &copy; les contributeurs d'OpenStreetMap,\n  CC-BY-SA&rdquo;.\n</p>\n<p>\n  Là où cela est possible, OpenStreetMap doit être un lien hypertexte vers <a\n  href=\"http://www.openstreetmap.org/\">http://www.openstreetmap.org/</a>\n  et CC-BY-SA vers <a\n  href=\"http://creativecommons.org/licenses/by-sa/2.0/\">http://creativecommons.org/licenses/by-sa/2.0/</a>.\n  Si vous utiliser un média qui ne permet pas de créer des liens (ex :\n  un imprimé), nous suggérons que vous dirigiez vos lecteurs vers\n  www.openstreetmap.org (peut-être en étendant\n  &lsquo;OpenStreetMap&rsquo; à l'adresse complète) et vers\n  www.creativecommons.org.\n</p>\n\n<h3>Plus d'informations</h3>\n<p>\n  Si vous voulez obtenir plus d'informations sur la réutilisation de nos données, lisez la <a\n  href=\"http://wiki.openstreetmap.org/wiki/Legal_FAQ\">FAQ légale</a>.\n</p>\n<p>\n  Nous rappelons aux contributeurs d'OSM qu'ils ne doivent jamais ajouter de données provenant\n  de sources sous copyright (ex : Google Maps ou des cartes imprimées) sans\n  autorisation explicite de la part des détenteurs du copyright.\n</p>\n<p>\n  Bien qu'OpenStreetMap soit un ensemble de données ouvertes, nous ne pouvons pas fournir\n  d'API libre de frais pour les développeurs tiers.\n\n  Voyez nos <a href=\"http://wiki.openstreetmap.org/wiki/API_usage_policy\">règles d'utilisation de l'API</a>,\n  <a href=\"http://wiki.openstreetmap.org/wiki/Tile_usage_policy\">règles d'utilisation de la carte</a>\n  et <a href=\"http://wiki.openstreetmap.org/wiki/Nominatim#Usage_Policy\">règles d'utilisation de Nominatim</a>.\n</p>\n\n<h3>Nos contributeurs</h3>\n<p>\n  Notre licence CC-BY-SA nécessite que vous &ldquo;donniez à l'auteur d'origine\n  un crédit raisonnable selon le média que vous utilisez&rdquo;.\n  Les cartographes individuels d'OSM ne demandent pas\n  d'autre crédit que &ldquo;les contributeurs d'OpenStreetMap&rdquo;,\n  mais lorsque des données venant d'une agence nationale de cartographie\n  ou autre source majeure ont été incluses dans OpenStreetMap,\n  il peut être raisonnable de les créditer directement\n  de la manière qu'ils demandent ou par un lien vers cette page.\n</p>\n\n<!--\nInformation pour ceux qui modifient cette page\n\nLa liste suivante ne contient que les organisations qui demandent l'attribution\ncomme condition de la présence de leur données dans OpenStreetMap. Ce n'est pas un\ncatalogue général des ajouts, et elle ne doit pas être utilisée,\nsauf lorsque l'attribution est nécessaire pour respecter la licence des données importées.\n\nTout ajout fait ici doit d'abord être discuté avec les administrateurs d'OSM.\n-->\n\n<ul id=\"contributors\">\n   <li><strong>Australie</strong>: Contient des données sur les banlieues\n   fondée sur les données de l'Australian Bureau of Statistics.</li>\n   <li><strong>Canada</strong>: Contient des données de\n   GeoBase&reg;, GeoGratis (&copy; Department of Natural\n   Resources Canada), CanVec (&copy; Department of Natural\n   Resources Canada), et StatCan (Geography Division,\n   Statistics Canada).</li>\n   <li><strong>Nouvelle-Zélende</strong>: Contient des données provenant du\n   Land Information New Zealand. Crown Copyright reserved.</li>\n   <li><strong>Royaume-Uni</strong>: Contient des données d'Ordnance\n   Survey data &copy; Crown copyright and database right 2010.</li>\n</ul>\n\n<p>\n  L'inclusion de données dans OpenStreetMap n'implique pas que les fournisseurs d'origine\n  du contenu approuvent OpenStreetMap, ni ne fournissent, ne garantissent ou n'acceptent quelque lien que ce soit.\n</p>"
+    native: 
+      mapping_link: commencer à ontribuer
+      native_link: version française
+      text: Vous lisez la version anglais de la page de copyright. Vous pouvez retourner à la {{native_link}} de cette page ou arrêter de lire cette page et {{mapping_link}}.
+      title: A propos de cette page
   message: 
     delete: 
       deleted: Message supprimé
index 150d648946184f27086ad8888befc6e81ab7c979..b64faf99eba32322b1f134c317f0035a673a110e 100644 (file)
@@ -128,7 +128,13 @@ hr:
     navigation: 
       all: 
         next_changeset_tooltip: Slijedeći changeset
+        next_node_tooltip: Sljedeća točka
+        next_relation_tooltip: Sljedeća relacija
+        next_way_tooltip: Sljedeći put
         prev_changeset_tooltip: Prethodni changeset
+        prev_node_tooltip: Prethodna točka
+        prev_relation_tooltip: Prethodna relacija
+        prev_way_tooltip: Prethodni put
       user: 
         name_changeset_tooltip: "Prikaži promjene korisnika:  {{user}}"
         next_changeset_tooltip: Slijedeća promjena od {{user}}
@@ -217,6 +223,10 @@ hr:
       zoom_or_select: Zoomiraj ili izaberi područje karte za pregled
     tag_details: 
       tags: "Oznake:"
+      wiki_link: 
+        key: Opis wiki stranica za oznaku {{key}} (tag)
+        tag: Opis wiki stranica za oznaku {{key}}={{value}} (tag)
+      wikipedia_link: Članak o {{page}} na Wikipediji
     timeout: 
       sorry: Žao mi je, podaci za {{type}} sa id {{id}}, predugo se čekaju.
       type: 
@@ -365,6 +375,7 @@ hr:
       paste_html: Zalijepi HTML za ubacivanje na webstranicu
       scale: Mjerilo
       too_large: 
+        body: Ovo područje je preveliko da bi se izvezlo kao OpenStreetMap XML podaci. Molimo povećajte (zoom) ili odaberite manju površinu.
         heading: Područje je preveliko
       zoom: Zoom
     start_rjs: 
@@ -857,9 +868,14 @@ hr:
         cycle_map: Biciklistička karta
         noname: Bezimene ulice
     site: 
+      edit_disabled_tooltip: Uvećajte za uređivanje karte
+      edit_tooltip: Uredi kartu
       edit_zoom_alert: Morate zoomirati da bi uređivali kartu
+      history_disabled_tooltip: Zoomirajte da biste vidjeli uređivanja za ovo područje
+      history_tooltip: Prikaži izmjene za ovo područje
       history_zoom_alert: Morate zoomirati da bi vidjeli povijest izmjena
   layouts: 
+    copyright: Autorska prava &amp; Dozvola
     donate: Podržite OpenStreetMap sa {{link}} Hardware Upgrade Fond.
     donate_link_text: donacije
     edit: Uredi
@@ -881,6 +897,9 @@ hr:
     intro_1: OpenStreetMap je slobodna, promjenjiva karta cijelog svijeta. Napravili su je ljudi slični tebi.
     intro_2: OpenStreetMap omogućava pregledavanje, uređivanje i korištenje geografskih podataka u suradničkom načinu od bilo gdje sa Zemlje.
     intro_3: Smještaj OpenStreetMapa je ljubazno podržan od {{ucl}} i {{bytemark}}. Ostali podržavatelji projekta su navedeni u {{partners}}.
+    intro_3_bytemark: bytemarka
+    intro_3_partners: wiki
+    intro_3_ucl: UCL VR Centra
     license: 
       title: OpenStreetMap podaci su objavljeni pod licencom Creative Commons Attribution-Share Alike 2.0 Generic License
     log_in: prijava
@@ -908,6 +927,17 @@ hr:
     view_tooltip: Pogledaj na karti
     welcome_user: Dobrodošli, {{user_link}}
     welcome_user_link_tooltip: Tvoja korisnička stranica
+  license_page: 
+    foreign: 
+      english_link: Engleski izvornik
+      text: U slučaju konflikta između ove prevedene stranice i {{english_original_link}}, Engleski stranice imaju prednost
+      title: O ovom prijevodu
+    legal_babble: "<h2>Autorska prava i Dozvola</h2>\n<p>\n   OpenStreetMap su <i>otvoreni podaci</i>, licencirani pod <a\n   href=\"http://creativecommons.org/licenses/by-sa/2.0/\">Creative\n   Commons Attribution-ShareAlike 2.0</a> dozvolom (CC-BY-SA).\n</p>\n<p>\n  Slobodni ste kopirati, distribuirati, prenositi i adaptirati naše karte\n  i podatke, sve dok navodite OpenStreetMap kao izvor i doprinositelje. Ako izmjenite \n  ili nadogradite naše karte ili podatke, možete distribuirati rezultate\n  samo pod istom licencom. Potpuna <a\n  href=\"http://creativecommons.org/licenses/by-sa/2.0/legalcode\">tekst</a> objašnjava prava i obaveze.\n</p>\n\n<h3>Kako navoditi OpenStreetMap kao izvor</h3>\n<p>\n  Ako koristite slike OpenstreetMap karte, zahtjevamo da\n  se navede najmanje &ldquo;&copy; OpenStreetMap\n  contributors, CC-BY-SA&rdquo;. Ako koristite samo podatke,\n  zahtjevamo &ldquo;Map data &copy; OpenStreetMap contributors,\n  CC-BY-SA&rdquo;.\n</p>\n<p>\n  Gdje je moguće, OpenStreetMap treba biti kao hyperlink na <a\n  href=\"http://www.openstreetmap.org/\">http://www.openstreetmap.org/</a>\n  and CC-BY-SA to <a\n  href=\"http://creativecommons.org/licenses/by-sa/2.0/\">http://creativecommons.org/licenses/by-sa/2.0/</a>. Ako\n  koristite medija gdje linkovi nisu mogući (npr. isprintane\n  karte), predlažemo da uputite vaše čitatelje na\n  www.openstreetmap.org (proširenjem na\n  &lsquo;OpenStreetMap&rsquo; za ovo punu adresu) i na\n  www.creativecommons.org.\n</p>\n\n<h3>Više o</h3>\n<p>\n  Čitajte više o korištenju naših podataka na <a\n  href=\"http://wiki.openstreetmap.org/wiki/Legal_FAQ\">Legal\n  FAQ</a>.\n</p>\n<p>\n  OSM korisnici - doprinostielji se podsjećaju da nikada ne dodaju podakte iz bilo kojeg\n  izvora zaštićenog autorskim pravima (npr. Google Maps ili tiskane karte) bez izričite dozvole\n  vlasnik autorskih prava.\n</p>\n<p>\n  Iako su OpenstreetMap otvoreni podaci, ne možemo pružiti\n  besplatni API za kartu za ostale developere.\n\n  Vidi našu <a href=\"http://wiki.openstreetmap.org/wiki/API_usage_policy\">Politiku korištenja API-a</a>,\n  <a href=\"http://wiki.openstreetmap.org/wiki/Tile_usage_policy\">Politiku korištenja pločica</a>\n  and <a href=\"http://wiki.openstreetmap.org/wiki/Nominatim#Usage_Policy\">Politiku korištenja Nominatim-a</a>.\n</p>\n\n<h3>Naši korisnici - doprinostielji</h3>\n<p>\n  Naša CC-BY-SA licenca zahtjeva od vas da &ldquo; navedete izvor Originala\n  reazumno prema mediju ili načinima koje koristite&rdquo;. \n  Pojedini OSM maperi ne traže navođenje njih preko ili više od\n  &ldquo;OpenStreetMap korisnici - doprinostielja&rdquo;, ali gdje su podaci\n  iz nacionalne agencije za kartiranje ili nekog drugog glavnog izvora uključeni u\n  OpenStreetMap, razumno je navesti i njih direktno\n  navodeći ime ili link na njihovu stranicu.\n</p>\n\n<!--\nInformacije za urednike stranica\n\nSlijedeće popisuje samo one organizacije koje zahtjevaju navođenje/ \npripisivanje kao uvijet da se njihovi podaci koriste u OpenStreetMap. \nOvo nije cjeloviti katalog \"uvoza\" podataka, i ne smije se koristiti osim\nkada se pripisivanje zahtjeva da bude u skladu s dozvolom uvezenih podataka.\n\nBilo koje dodavanje ovdje, najprije se mora raspraviti s OSM sistemskim administratorima.\n-->\n\n<ul id=\"contributors\">\n   <li><strong>Australija</strong>: Sadrži podatke o predgrađima na osnovu podataka Australian Bureau of Statistics.</li>\n   <li><strong>Kanada</strong>: Sadrži podatke iz\n   GeoBase&reg;, GeoGratis (&copy; Department of Natural\n   Resources Canada), CanVec (&copy; Department of Natural\n   Resources Canada), i StatCan (Geography Division,\n   Statistics Canada).</li>\n   <li><strong>Novi Zeland</strong>: Sadrži podatke izvorno iz\n   Land Information New Zealand. Crown Copyright reserved.</li>\n   <li><strong>Velika Britanija</strong>: Sadrži podatke Ordnance\n   Survey data &copy; Crown copyright and database right\n   2010.</li>\n</ul>\n\n<p>\n  Uvrštenje podataka u OpenStreetMap ne podrazumjeva da se izvorni\n  davatelj podataka podržava OpenStreetMap, pruža bilo kakovo jamstvo, ili \n  prihvaća bilo kakve obveze.\n</p>"
+    native: 
+      mapping_link: počnite kartirati
+      native_link: HRVATSKI verzija
+      text: Vi gledate englesku verziju stranice o autorskim pravima. Možete se vratiti na {{native_link}} ove stranice ili možete prestati čitati o autorskim pravima i {{mapping_link}}.
+      title: O ovoj stranici
   message: 
     delete: 
       deleted: Poruka obrisana
@@ -939,12 +969,13 @@ hr:
       subject: Tema
       title: Pošalji poruku
     no_such_message: 
+      body: Nažalost nema poruka s tim id.
       heading: Nema takve poruke
       title: Nema takve poruke
     no_such_user: 
       body: Nažalost ne postoji korisnik s tim imenom.
       heading: Nema takvog korisnika
-      title: Nema takvog korisnika ili poruke
+      title: Nema takvog korisnika
     outbox: 
       date: Datum
       inbox: dolazna pošta
@@ -988,6 +1019,7 @@ hr:
       hopefully_you_1: Netko (nadam se ti) želio bi promjeniti njihove email adrese preko u
       hopefully_you_2: "{{server_url}} na {{new_address}}."
     friend_notification: 
+      befriend_them: Također, možete ih dodati kao prijatelja na {{befriendurl}}.
       had_added_you: "{{user}} te je dodao kao prijatelja na OpenStreetMap-u."
       see_their_profile: Možeš vidjeti njihov profil na {{userurl}}.
       subject: "[OpenStreetMap] {{user}} te je dodao kao prijatelja"
@@ -1320,14 +1352,21 @@ hr:
       trackable: Trackable-može se pratiti (prikazuje se kao anonimne, posložene točke sa vremenskom oznakom)
   user: 
     account: 
+      current email address: "Trenutna E-mail adresa:"
+      delete image: Uklonite trenutnu sliku
       email never displayed publicly: (nikada se ne prikazuje javno)
       flash update success: Korisničke informacije su uspješno ažurirane.
       flash update success confirm needed: Korisničke informacije su uspješno ažurirane. Provjerite email za porukom za potvrdu nove email adrese.
       home location: "Dom:"
+      image: "Slika:"
+      image size hint: (kvadratne slike od barem 100x100 pixela rade najbolje)
+      keep image: Zadržite trenutnu sliku
       latitude: "Geografska širina (Latitude):"
       longitude: "Geografska dužina (Longitude):"
       make edits public button: Napravi sve moje promjene javnim
       my settings: Moje postavke
+      new email address: "Nova E-mail adresa:"
+      new image: Dodajte sliku
       no home location: Niste unjeli lokaciju vašeg doma.
       preferred languages: "Željeni jezici:"
       profile description: "Opis profila:"
@@ -1341,6 +1380,7 @@ hr:
       public editing note: 
         heading: Javno uređivanje
         text: Trenutno su vaše izmjene anonimne i ljudi vam ne mogu poslati poruke ili vidjeti vašu lokaciju. Da bi pokazali vaše izmjene i dozvolili ljudima da vas kontaktiraju preko website-a, kliknite gumb ispod <b>Od promjene 0.6 API-a, samo javni korisnici mogu uređivati karte</b>. (<a href="http://wiki.openstreetmap.org/wiki/Anonymous_edits">saznajte zašto</a>).<ul> <li>Vaša email adrea neće biti otkrivena ako postanete javni.</li> <li>Ova akcija se ne može poništiti i svi novi korisnici su postavljeni kao javni.</li> </ul>
+      replace image: Zamijenite trenutnu sliku
       return to profile: Vrati se na profil
       save changes button: Snimi promjene
       title: Uredi korisnički račun
@@ -1371,9 +1411,12 @@ hr:
       lost password link: Izgubljena lozinka?
       password: "Lozinka:"
       please login: Molimo prijavite se ili {{create_user_link}}.
+      remember: "Zapamti me:"
       title: Prijava
     logout: 
       heading: Odjava iz OpenStreetMap
+      logout_button: Odjava
+      title: Odjava
     lost_password: 
       email address: "Email adresa:"
       heading: Zaboravljena lozinka?
@@ -1407,6 +1450,7 @@ hr:
       heading: Korisnik {{user}}  ne postoji
       title: Nema takvog korisnika
     popup: 
+      friend: Prijatelj
       nearby mapper: Obližnji maper
       your location: Vaša lokacija
     remove_friend: 
@@ -1451,7 +1495,7 @@ hr:
       nearby users: Drugi korisnici u blizini
       new diary entry: novi unos u dnevnik
       no friends: Nisi dodao niti jednog prijatelja.
-      no nearby users: Nema okolnih korisnika koji mapiraju.
+      no nearby users: Još uvijek nema drugih korisnika koji kartiraju-mapiraju u blizini.
       oauth settings: oauth postavke
       remove as friend: ukloni kao prijatelja
       role: 
index e72b4208fc15c2706031ea38e896978fde2f53c2..9e82b21847debf888f71e1739d6e923a5606d4b7 100644 (file)
@@ -123,7 +123,13 @@ ia:
     navigation: 
       all: 
         next_changeset_tooltip: Gruppo de modificationes sequente
+        next_node_tooltip: Nodo sequente
+        next_relation_tooltip: Relation sequente
+        next_way_tooltip: Via sequente
         prev_changeset_tooltip: Gruppo de modificationes precedente
+        prev_node_tooltip: Nodo precedente
+        prev_relation_tooltip: Relation precedente
+        prev_way_tooltip: Via precedente
       user: 
         name_changeset_tooltip: Vider modifications per {{user}}
         next_changeset_tooltip: Modification sequente per {{user}}
@@ -212,6 +218,9 @@ ia:
       zoom_or_select: Face zoom avante o selige un area del carta a visualisar
     tag_details: 
       tags: "Etiquettas:"
+      wiki_link: 
+        key: Le pagina wiki que describe le etiquetta {{key}}
+        tag: Le pagina wiki que describe le etiquetta {{key}}={{value}}
       wikipedia_link: Le articulo {{page}} in Wikipedia
     timeout: 
       sorry: Pardono, le datos pro le {{type}} con le ID {{id}} ha prendite troppo de tempore pro esser recuperate.
@@ -500,6 +509,33 @@ ia:
           waste_basket: Corbe a papiro
           wifi: Accesso WiFi
           youth_centre: Centro pro le juventute
+        boundary: 
+          administrative: Limite administrative
+        building: 
+          apartments: Bloco de appartamentos
+          chapel: Cappella
+          church: Ecclesia
+          city_hall: Casa municipal
+          commercial: Edificio commercial
+          entrance: Entrata de edificio
+          faculty: Edificio de facultate
+          farm: Edificio agricole
+          flats: Appartamentos
+          garage: Garage
+          hospital: Edificio hospitalari
+          hotel: Hotel
+          house: Casa
+          industrial: Edificio industrial
+          public: Edificio public
+          retail: Magazin
+          school: Edificio de schola
+          stadium: Stadio
+          store: Magazin
+          terrace: Terrassa
+          tower: Turre
+          train_station: Station ferroviari
+          university: Edificio de universitate
+          "yes": Edificio
         highway: 
           bridleway: Sentiero pro cavallos
           bus_guideway: Via guidate de autobus
@@ -718,17 +754,26 @@ ia:
           viewpoint: Puncto de vista
           zoo: Zoo
         waterway: 
+          boatyard: Cantier naval
+          canal: Canal
+          connector: Connexion aquatic
+          dam: Dica
           derelict_canal: Canal abandonate
           ditch: Fossato
           dock: Dock
           drain: Aquiero
           lock: Esclusa
           lock_gate: Porta de esclusa
+          mineral_spring: Fonte de aqua mineral
           mooring: Ammarrage
           rapids: Rapidos
           river: Fluvio/Riviera
           riverbank: Ripa de fluvio/riviera
+          stream: Rivo
+          wadi: Wadi
+          water_point: Puncto de aqua
           waterfall: Cascada
+          weir: Barrage
   javascripts: 
     map: 
       base: 
@@ -787,6 +832,17 @@ ia:
     view_tooltip: Vider le carta
     welcome_user: Benvenite, {{user_link}}
     welcome_user_link_tooltip: Tu pagina de usator
+  license_page: 
+    foreign: 
+      english_link: le original in anglese
+      text: In caso de un conflicto inter iste pagina traducite e {{english_original_link}}, le pagina in anglese prevalera.
+      title: A proposito de iste traduction
+    legal_babble: "<h2>Copyright e Licentia</h2>\n<p>\n   OpenStreetMap es <i>datos aperte</i>, disponibile sub le licentia\n   <a href=\"http://creativecommons.org/licenses/by-sa/2.0/\">Creative\n   Commons Attribution-ShareAlike 2.0</a> (CC-BY-SA).\n</p>\n<p>\n  Vos es libere de copiar, distribuer, transmitter e adaptar nostre cartas\n  e datos, a condition que vos da recognoscentia a OpenStreetMap e su\n  contributores. Si vos altera o extende nostre cartas e datos, vos\n  pote distribuer le resultato solmente sub le mesme licentia. Le\n  complete <a\n  href=\"http://creativecommons.org/licenses/by-sa/2.0/legalcode\">codice\n  legal</a> explica vostre derectos e responsabilitates.\n</p>\n\n<h3>Como dar recognoscentia a OpenStreetMap</h3>\n<p>\n  Si vos usa imagines del cartas de OpenStreetMap, nos requesta que\n  vostre recognoscentia indica al minus &ldquo;&copy; Contributores de\n  OpenStreetMap, CC-BY-SA&rdquo;. Si vos usa solmente datos cartographic,\n  nos requesta &ldquo;Datos cartographic &copy; Contributores de OpenStreetMap,\n  CC-BY-SA&rdquo;.\n</p>\n<p>\n  Si possibile, le parola OpenStreetMap debe esser un hyperligamine a <a\n  href=\"http://www.openstreetmap.org/\">http://www.openstreetmap.org/</a>\n  e le termino CC-BY-SA debe ligar a <a\n  href=\"http://creativecommons.org/licenses/by-sa/2.0/\">http://creativecommons.org/licenses/by-sa/2.0/</a>. Si\n  vos usa un medio de communication in le qual le ligamines non es possibile (p.ex. un\n  obra imprimite), nos suggere que vos dirige vostre lectores a\n  www.openstreetmap.org (possibilemente per expander\n  &lsquo;OpenStreetMap&rsquo; a iste adresse complete) e a\n  www.creativecommons.org.\n</p>\n\n<h3>Pro saper plus</h3>\n<p>\n  Lege plus super le uso de nostre datos al <a\n  href=\"http://wiki.openstreetmap.org/wiki/Legal_FAQ\">FAQ\n  Legal</a>.\n</p>\n<p>\n  Le contributores de OSM es recordate de nunquam adder datos de alcun\n  fonte subjecte al derecto de autor (p.ex. Google Maps o cartas imprimite)\n  sin explicite permission del titulares del derecto de autor.\n</p>\n<p>\n  Ben que OpenStreetMap es datos aperte, nos non pote fornir un\n  API cartographic gratuite pro altere disveloppatores.\n\n  Vide nostre <a href=\"http://wiki.openstreetmap.org/wiki/API_usage_policy\">politica pro le uso del API</a>,\n  <a href=\"http://wiki.openstreetmap.org/wiki/Tile_usage_policy\">politica pro le uso de tegulas</a>\n  e <a href=\"http://wiki.openstreetmap.org/wiki/Nominatim#Usage_Policy\">politica pro le uso de Nominatim</a>.\n</p>\n\n<h3>Nostre contributores</h3>\n<p>\n  Nostre licentia CC-BY-SA require que vos &ldquo;da al Autor\n  Original recognoscentia rationabile pro le medio que Vos\n  utilisa&rdquo;. Le cartographos individual de OSM non requesta un\n  recognoscentia excedente illo del &ldquo;Contributores de\n  OpenStreetMap&rdquo;, sed ubi datos de un agentia cartographic\n  national o altere fonte major ha essite includite in\n  OpenStreetMap, il pote esser rationabile dar les recognoscentia per\n  directemente reproducer lor recognoscentia o per ligar a illo in iste pagina.\n</p>\n\n<!--\nInformation pro redactores de iste pagina\n\nIn le sequente lista figura solmente le organisationes que require attribution\ncomo condition pro le uso de lor datos in OpenStreetMap. Isto non es un\ncatalogo general de datos importate, e non debe esser usate salvo si\nattribution es requirite pro conformitate con le licentia del datos\nimportate.\n\nOmne additiones hic debe esser discutite primo con le administratores de OSM.\n-->\n\n<ul id=\"contributors\">\n   <li><strong>Australia</strong>: Contine datos de suburbios a base\n   de datos del Australian Bureau of Statistics.</li>\n   <li><strong>Canada</strong>: Contine datos ab\n   GeoBase&reg;, GeoGratis (&copy; Department of Natural\n   Resources Canada), CanVec (&copy; Department of Natural\n   Resources Canada), e (Geography Division,\n   Statistics Canada).</li>\n   <li><strong>Nove Zelandia</strong>: Contine datos obtenite ex\n   Land Information New Zealand. Crown Copyright reservate.</li>\n   <li><strong>Regno Unite</strong>: Contine datos de Ordnance\n   Survey &copy; Crown copyright e derecto de base de datos\n   2010.</li>\n</ul>\n\n<p>\n  Le inclusion de datos in OpenStreetMap non implica que le fornitor\n  original del datos indorsa OpenStreetMap, forni alcun garantia, o\n  accepta alcun responsabilitate.\n</p>"
+    native: 
+      mapping_link: comenciar le cartographia
+      native_link: version in interlingua
+      text: Tu vide nunc le version in anglese del pagina de copyright. Tu pote retornar al {{native_link}} de iste pagina o tu pote cessar de leger super copyright e {{mapping_link}}.
+      title: A proposito de iste pagina
   message: 
     delete: 
       deleted: Message delite
index 4a03b20c267894a35f751e492dff2b596b20ee71..fe9d18a019049633771511dd5db1cabe7a08ee0c 100644 (file)
@@ -880,7 +880,7 @@ ru:
       history_tooltip: Просмотр правок в этой области
       history_zoom_alert: Необходимо увеличить масштаб карты, чтобы увидеть историю правок
   layouts: 
-    copyright: Авт. право и лицензия
+    copyright: Авторское право и лицензия
     donate: Поддержите OpenStreetMap {{link}} в Фонд обновления оборудования.
     donate_link_text: пожертвованиями
     edit: Правка
@@ -931,6 +931,16 @@ ru:
     view_tooltip: Посмотреть карту
     welcome_user: Добро пожаловать, {{user_link}}
     welcome_user_link_tooltip: Ваша страница пользователя
+  license_page: 
+    foreign: 
+      english_link: английского оригинала
+      text: В случае конфликта между этой переведённой страницей и {{english_original_link}}, английская страница должна иметь приоритет
+      title: Об этом переводе
+    native: 
+      mapping_link: начать картографирование
+      native_link: русской версии
+      text: Вы просматриваете английскую версию страницы авторских прав. Вы можете вернуться к {{native_link}} этой страницы или можете прекратить чтение об авторских правах и {{mapping_link}}.
+      title: Об этой странице
   message: 
     delete: 
       deleted: Сообщение удалено
index bc6809c9086163a9e2098ba6e7782eb3477e828b..5286cdd6c0abb45780877e17c2519c5efcd39007 100644 (file)
@@ -2,6 +2,7 @@
 # Exported from translatewiki.net
 # Export driver: syck
 # Author: Minh Nguyen
+# Author: Ninomax
 vi: 
   activerecord: 
     attributes: 
@@ -123,7 +124,11 @@ vi:
     navigation: 
       all: 
         next_changeset_tooltip: Bộ thay đổi sau
+        next_node_tooltip: Node tiếp theo
+        next_way_tooltip: Đường tiếp theo
         prev_changeset_tooltip: Bộ thay đổi trước
+        prev_node_tooltip: Node trước
+        prev_relation_tooltip: Relation trước
       user: 
         name_changeset_tooltip: Xem các đóng góp của {{user}}
         next_changeset_tooltip: Đóng góp sau của {{user}}
@@ -422,6 +427,7 @@ vi:
           bench: Ghế
           bicycle_parking: Chỗ Đậu Xe đạp
           bicycle_rental: Chỗ Mướn Xe đạp
+          bus_station: Trạm xe bus
           cafe: Quán Cà phê
           car_rental: Chỗ Mướn Xe
           car_sharing: Chia sẻ Xe cộ
@@ -466,6 +472,7 @@ vi:
           post_office: Bưu điện
           preschool: Trường Mầm non
           prison: Nhà tù
+          pub: Quán rượu
           public_market: Chợ phiên
           restaurant: Nhà hàng
           sauna: Nhà Tắm hơi
@@ -797,6 +804,12 @@ vi:
     view_tooltip: Xem bản đồ
     welcome_user: Hoan nghênh, {{user_link}}
     welcome_user_link_tooltip: Trang cá nhân của bạn
+  license_page: 
+    foreign: 
+      english_link: nguyên bản tiếng Anh
+      text: Trong trường hợp có xung đột giữa trang dịch và trang {{english_original_link}}, trang tiếng Anh sẽ được ưu tiên
+    native: 
+      title: Giới thiệu về trang này
   message: 
     delete: 
       deleted: Đã xóa thư
index eccc3e95349b25427f8bda52dcc62350edd2aa80..624f7034b2dd59edf5da6b4248feb264b8095b26 100644 (file)
@@ -132,6 +132,7 @@ ca:
   option_layer_ooc_scotland: "Regne Unit històric: Escòcia"
   option_layer_os_streetview: "UK: OS StreetView"
   option_layer_streets_haiti: "Haití: noms de carrers"
+  option_layer_surrey_air_survey: "Regne Unit: Mesurament aeri de Surrey"
   option_layer_tip: Escollir el fons a mostrar
   option_limitways: Avisar si hi ha molta càrrega de dades
   option_microblog_id: "Nom microblog:"
index 90312ed08f66b12120a5d8c49705e2fc9385b667..e4f36fccb5c23270b71e63f56e83603fd49539e2 100644 (file)
@@ -136,12 +136,13 @@ de:
   option_layer_cycle_map: OSM - Radwanderkarte
   option_layer_maplint: OSM - Maplint (Fehler)
   option_layer_nearmap: "Australien: NearMap"
-  option_layer_ooc_25k: Historische UK Karten 1:25k
-  option_layer_ooc_7th: "UK historic: 7th"
-  option_layer_ooc_npe: "UK historic: NPE"
-  option_layer_ooc_scotland: "UK-Historisch: Schottland"
+  option_layer_ooc_25k: "UK (historisch): Karten 1:25k"
+  option_layer_ooc_7th: "UK (historisch): 7th"
+  option_layer_ooc_npe: "UK (historisch): NPE"
+  option_layer_ooc_scotland: "UK (historisch): Schottland"
   option_layer_os_streetview: "UK: OS StreetView"
   option_layer_streets_haiti: "Haiti: Straßenname"
+  option_layer_surrey_air_survey: "UK: Surrey Air Survey"
   option_layer_tip: Hintergrund auswählen
   option_limitways: Warnung wenn große Datenmenge geladen wird
   option_microblog_id: "Microblog Name:"
index 54abd6047d9e1b7c2e63cf2920b89918e4e96696..1fbffb1c08fc8b3d62048026fd85b92e4274ba94 100644 (file)
@@ -125,12 +125,13 @@ gl:
   option_layer_cycle_map: OSM - mapa cíclico
   option_layer_maplint: OSM - Maplint (erros)
   option_layer_nearmap: "Australia: NearMap"
-  option_layer_ooc_25k: "Historial UK: 1:25k"
-  option_layer_ooc_7th: "Historial UK: 7º"
-  option_layer_ooc_npe: "Historial UK: NPE"
-  option_layer_ooc_scotland: "RU histórico: Escocia"
-  option_layer_os_streetview: "RU: OS StreetView"
+  option_layer_ooc_25k: "Reino Unido histórico: 1:25k"
+  option_layer_ooc_7th: "Reino Unido histórico: 7º"
+  option_layer_ooc_npe: "Reino Unido histórico: NPE"
+  option_layer_ooc_scotland: "Reino Unido histórico: Escocia"
+  option_layer_os_streetview: "Reino Unido: OS StreetView"
   option_layer_streets_haiti: "Haití: nomes de rúas"
+  option_layer_surrey_air_survey: "Reino Unido: Enquisa aérea sobre Surrey"
   option_layer_tip: Escolla o fondo a mostrar
   option_limitways: Avisar ao cargar moitos datos
   option_microblog_id: "Nome do blogue de mensaxes curtas:"
index ae9de0ad25b6c28681718bcd708f5b01f2ff369a..96dddff71cad61618c14213eb861c9df81719161 100644 (file)
@@ -32,6 +32,7 @@ hr:
   advanced_tooltip: Napredne uređivačke akcije
   advanced_undelete: Vrati obrisano
   advice_bendy: Previše zavojito za izravnavanje (SHIFT za nasilno)
+  advice_conflict: Konflikt na serveru - možda ćete morati ponovno pokušati spremiti
   advice_deletingpoi: Brisanje POI (Z - poništi)
   advice_deletingway: Brisanje puta (poništi sa Z)
   advice_microblogged: $1 status je ažuriran
@@ -89,6 +90,7 @@ hr:
   hint_saving: Spremanje podataka
   hint_saving_loading: učitavanje/spremanje podataka
   inspector: Inspektor
+  inspector_duplicate: "Duplikat od:"
   inspector_in_ways: U putevima
   inspector_latlon: "Lat $1\nLon $2"
   inspector_locked: Zaključan
@@ -100,6 +102,7 @@ hr:
   inspector_way_connects_to_principal: Spaja se na $1 $2 i $3 drugi $4
   inspector_way_nodes: $1 točke
   inspector_way_nodes_closed: $1 točaka (zatvoren)
+  loading: Učitavam...
   login_pwd: "Lozinka:"
   login_retry: Prijava na site nije prepoznata. Pokušajte ponovo.
   login_title: Ne mogu se prijaviti
@@ -179,13 +182,19 @@ hr:
   prompt_microblog: Šalji na $1 ($2 ostalo)
   prompt_revertversion: "Vrati na prijašnju spremljenu verziju:"
   prompt_savechanges: Spremi promjene
-  prompt_taggedpoints: Neke točke na ovom putu su označene (Tags). Stvarno obrisati?
+  prompt_taggedpoints: Neke od točaka na tom putu su označene ili u relacijama. Želite izbrisati?
   prompt_track: Pretvori GPS trag u put
   prompt_unlock: Klik za otključavanje
   prompt_welcome: Dobrodošli na OpenStreetMap!
   retry: Pokušaj ponovo
   revert: Vrati na staro
   save: Spremi
+  tags_backtolist: Povratak na listu
+  tags_descriptions: Opisi '$1'
+  tags_findatag: Pronađi oznaku (tag)
+  tags_findtag: Pronađi oznaku (tag)
+  tags_matching: Popularne oznake koje odgovaraju '$1'
+  tags_typesearchterm: "Unesite riječ za pretragu:"
   tip_addrelation: Dodaj relaciji
   tip_addtag: Dodaj novu oznaku (Tag)
   tip_alert: Došlo je do greške - klikni za detalje
index f041f125b7d0307240b9b35c3313bb3c514e11d0..4c68721f699ac0d443aaf1c08635eecbde2bcd72 100644 (file)
@@ -142,6 +142,7 @@ ru:
   option_layer_os_streetview: "UK: OS StreetView"
   option_layer_osmarender: OSM - Osmarender
   option_layer_streets_haiti: "Гаити: названия улиц"
+  option_layer_surrey_air_survey: "UK: Surrey Air Survey"
   option_layer_tip: Выберите фон
   option_layer_yahoo: Yahoo!
   option_limitways: Предупрежд. когда много данных
index 11f86e000e7094dbaf200e3664813c95d7ca115a..1c67eaa6eb7dde8a115b84920a0b5d45b4348ee1 100644 (file)
@@ -105,6 +105,7 @@ ActionController::Routing::Routes.draw do |map|
   map.connect '/user/go_public', :controller => 'user', :action => 'go_public'
   map.connect '/user/reset-password', :controller => 'user', :action => 'reset_password'
   map.connect '/user/forgot-password', :controller => 'user', :action => 'lost_password'
+  map.connect '/user/suspended', :controller => 'user', :action => 'suspended'
 
   map.connect '/index.html', :controller => 'site', :action => 'index'
   map.connect '/edit.html', :controller => 'site', :action => 'edit'
@@ -159,10 +160,7 @@ ActionController::Routing::Routes.draw do |map|
   map.connect '/user/:display_name/diary/:id/hide', :controller => 'diary_entry', :action => 'hide', :id => /\d+/
   map.connect '/user/:display_name/diary/:id/hidecomment/:comment', :controller => 'diary_entry', :action => 'hidecomment', :id => /\d+/, :comment => /\d+/
   map.connect '/user/:display_name/account', :controller => 'user', :action => 'account'
-  map.connect '/user/:display_name/activate', :controller => 'user', :action => 'activate'
-  map.connect '/user/:display_name/deactivate', :controller => 'user', :action => 'deactivate'
-  map.connect '/user/:display_name/hide', :controller => 'user', :action => 'hide'
-  map.connect '/user/:display_name/unhide', :controller => 'user', :action => 'unhide'
+  map.connect '/user/:display_name/set_status', :controller => 'user', :action => 'set_status'
   map.connect '/user/:display_name/delete', :controller => 'user', :action => 'delete'
   map.connect '/diary/new', :controller => 'diary_entry', :action => 'new'
   map.connect '/diary', :controller => 'diary_entry', :action => 'list'
@@ -170,7 +168,10 @@ ActionController::Routing::Routes.draw do |map|
   map.connect '/diary/:language', :controller => 'diary_entry', :action => 'list'
   map.connect '/diary/:language/rss', :controller => 'diary_entry', :action => 'rss'
 
-  
+  # user lists
+  map.connect '/users', :controller => 'user', :action => 'list'
+  map.connect '/users/:status', :controller => 'user', :action => 'list'
+
   # test pages
   map.connect '/test/populate/:table/:from/:count', :controller => 'test', :action => 'populate'
   map.connect '/test/populate/:table/:count', :controller => 'test', :action => 'populate', :from => 1
diff --git a/db/migrate/050_add_user_index_to_diary_comments.rb b/db/migrate/050_add_user_index_to_diary_comments.rb
new file mode 100644 (file)
index 0000000..e1fe0de
--- /dev/null
@@ -0,0 +1,9 @@
+class AddUserIndexToDiaryComments < ActiveRecord::Migration
+  def self.up
+    add_index :diary_comments, [:user_id, :created_at], :name => "diary_comment_user_id_created_at_index"
+  end
+
+  def self.down
+    remove_index :diary_comments, :name => "diary_comment_user_id_created_at_index"
+  end
+end
diff --git a/db/migrate/051_add_status_to_user.rb b/db/migrate/051_add_status_to_user.rb
new file mode 100644 (file)
index 0000000..cc8a2f2
--- /dev/null
@@ -0,0 +1,29 @@
+require 'lib/migrate'
+
+class AddStatusToUser < ActiveRecord::Migration
+  def self.up
+    create_enumeration :user_status_enum, ["pending","active","confirmed","suspended","deleted"]
+
+    add_column :users, :status, :user_status_enum, :null => false, :default => "pending"
+
+    User.update_all("status = 'deleted'", { :visible => false })
+    User.update_all("status = 'pending'", { :visible => true, :active => 0 })
+    User.update_all("status = 'active'", { :visible => true, :active => 1 })
+
+    remove_column :users, :active
+    remove_column :users, :visible
+  end
+
+  def self.down
+    add_column :users, :visible, :boolean, :default => true, :null => false
+    add_column :users, :active, :integer, :default => 0, :null => false
+
+    User.update_all("visible = true, active = 1", { :status => "active" })
+    User.update_all("visible = true, active = 0", { :status => "pending" })
+    User.update_all("visible = false, active = 1", { :status => "deleted" })
+
+    remove_column :users, :status
+
+    drop_enumeration :user_status_enum
+  end
+end
index b5f3cb1aa4fa92aea0c32133c865c27b90615c00..c92655aeea207b48393645e6bb9aeb4bcf478c4c 100644 (file)
@@ -7,6 +7,7 @@ module OSM
   require 'xml/libxml'
   require 'digest/md5'
   require 'RMagick'
+  require 'nokogiri'
 
   # The base class for API Errors.
   class APIError < RuntimeError
@@ -508,10 +509,30 @@ module OSM
     return "#{tilesql} AND #{prefix}latitude BETWEEN #{minlat} AND #{maxlat} AND #{prefix}longitude BETWEEN #{minlon} AND #{maxlon}"
   end
 
+  # Return a spam score for a chunk of text
+  def self.spam_score(text)
+    link_count = 0
+    link_size = 0
+
+    doc = Nokogiri::HTML(text)
+
+    if doc.content.length > 0
+      doc.xpath("//a").each do |link|
+        link_count += 1
+        link_size += link.content.length
+      end
+
+      link_proportion = link_size.to_f / doc.content.length.to_f
+    else
+      link_proportion = 0
+    end
+
+    return [link_proportion - 0.2, 0.0].max * 200 + link_count * 20
+  end
+
   def self.legal_text_for_country(country_code)
     file_name = File.join(RAILS_ROOT, "config", "legales", country_code.to_s + ".yml")
     file_name = File.join(RAILS_ROOT, "config", "legales", APP_CONFIG['default_legale'] + ".yml") unless File.exist? file_name
     YAML::load_file(file_name)
   end
-
 end
index ed98776539ce826e2ad36d36c85ebb308f6df778..fe7a99241521fe909ed9b9744969aa5a873883d7 100644 (file)
@@ -94,7 +94,7 @@ var OpenLayers={singleFile:true};(function(){var singleFile=(typeof OpenLayers==
 scriptLocation="";var isOL=new RegExp("(^|(.*?\\/))("+OpenLayers._scriptName+")(\\?|$)");var scripts=document.getElementsByTagName('script');for(var i=0,len=scripts.length;i<len;i++){var src=scripts[i].getAttribute('src');if(src){var match=src.match(isOL);if(match){scriptLocation=match[1];break;}}}
 return scriptLocation;}};if(!singleFile){var jsfiles=new Array("OpenLayers/Util.js","OpenLayers/BaseTypes.js","OpenLayers/BaseTypes/Class.js","OpenLayers/BaseTypes/Bounds.js","OpenLayers/BaseTypes/Element.js","OpenLayers/BaseTypes/LonLat.js","OpenLayers/BaseTypes/Pixel.js","OpenLayers/BaseTypes/Size.js","OpenLayers/Console.js","OpenLayers/Tween.js","Rico/Corner.js","Rico/Color.js","OpenLayers/Ajax.js","OpenLayers/Events.js","OpenLayers/Request.js","OpenLayers/Request/XMLHttpRequest.js","OpenLayers/Projection.js","OpenLayers/Map.js","OpenLayers/Layer.js","OpenLayers/Icon.js","OpenLayers/Marker.js","OpenLayers/Marker/Box.js","OpenLayers/Popup.js","OpenLayers/Tile.js","OpenLayers/Tile/Image.js","OpenLayers/Tile/Image/IFrame.js","OpenLayers/Tile/WFS.js","OpenLayers/Layer/Image.js","OpenLayers/Layer/SphericalMercator.js","OpenLayers/Layer/EventPane.js","OpenLayers/Layer/FixedZoomLevels.js","OpenLayers/Layer/Google.js","OpenLayers/Layer/VirtualEarth.js","OpenLayers/Layer/Yahoo.js","OpenLayers/Layer/HTTPRequest.js","OpenLayers/Layer/Grid.js","OpenLayers/Layer/MapGuide.js","OpenLayers/Layer/MapServer.js","OpenLayers/Layer/MapServer/Untiled.js","OpenLayers/Layer/KaMap.js","OpenLayers/Layer/KaMapCache.js","OpenLayers/Layer/MultiMap.js","OpenLayers/Layer/Markers.js","OpenLayers/Layer/Text.js","OpenLayers/Layer/WorldWind.js","OpenLayers/Layer/ArcGIS93Rest.js","OpenLayers/Layer/WMS.js","OpenLayers/Layer/WMS/Untiled.js","OpenLayers/Layer/WMS/Post.js","OpenLayers/Layer/ArcIMS.js","OpenLayers/Layer/GeoRSS.js","OpenLayers/Layer/Boxes.js","OpenLayers/Layer/XYZ.js","OpenLayers/Layer/TMS.js","OpenLayers/Layer/TileCache.js","OpenLayers/Layer/Zoomify.js","OpenLayers/Popup/Anchored.js","OpenLayers/Popup/AnchoredBubble.js","OpenLayers/Popup/Framed.js","OpenLayers/Popup/FramedCloud.js","OpenLayers/Feature.js","OpenLayers/Feature/Vector.js","OpenLayers/Feature/WFS.js","OpenLayers/Handler.js","OpenLayers/Handler/Click.js","OpenLayers/Handler/Hover.js","OpenLayers/Handler/Point.js","OpenLayers/Handler/Path.js","OpenLayers/Handler/Polygon.js","OpenLayers/Handler/Feature.js","OpenLayers/Handler/Drag.js","OpenLayers/Handler/RegularPolygon.js","OpenLayers/Handler/Box.js","OpenLayers/Handler/MouseWheel.js","OpenLayers/Handler/Keyboard.js","OpenLayers/Control.js","OpenLayers/Control/Attribution.js","OpenLayers/Control/Button.js","OpenLayers/Control/ZoomBox.js","OpenLayers/Control/ZoomToMaxExtent.js","OpenLayers/Control/DragPan.js","OpenLayers/Control/Navigation.js","OpenLayers/Control/MouseDefaults.js","OpenLayers/Control/MousePosition.js","OpenLayers/Control/OverviewMap.js","OpenLayers/Control/KeyboardDefaults.js","OpenLayers/Control/PanZoom.js","OpenLayers/Control/PanZoomBar.js","OpenLayers/Control/ArgParser.js","OpenLayers/Control/Permalink.js","OpenLayers/Control/Scale.js","OpenLayers/Control/ScaleLine.js","OpenLayers/Control/Snapping.js","OpenLayers/Control/Split.js","OpenLayers/Control/LayerSwitcher.js","OpenLayers/Control/DrawFeature.js","OpenLayers/Control/DragFeature.js","OpenLayers/Control/ModifyFeature.js","OpenLayers/Control/Panel.js","OpenLayers/Control/SelectFeature.js","OpenLayers/Control/NavigationHistory.js","OpenLayers/Control/Measure.js","OpenLayers/Control/WMSGetFeatureInfo.js","OpenLayers/Control/Graticule.js","OpenLayers/Control/TransformFeature.js","OpenLayers/Geometry.js","OpenLayers/Geometry/Rectangle.js","OpenLayers/Geometry/Collection.js","OpenLayers/Geometry/Point.js","OpenLayers/Geometry/MultiPoint.js","OpenLayers/Geometry/Curve.js","OpenLayers/Geometry/LineString.js","OpenLayers/Geometry/LinearRing.js","OpenLayers/Geometry/Polygon.js","OpenLayers/Geometry/MultiLineString.js","OpenLayers/Geometry/MultiPolygon.js","OpenLayers/Geometry/Surface.js","OpenLayers/Renderer.js","OpenLayers/Renderer/Elements.js","OpenLayers/Renderer/SVG.js","OpenLayers/Renderer/Canvas.js","OpenLayers/Renderer/VML.js","OpenLayers/Layer/Vector.js","OpenLayers/Layer/Vector/RootContainer.js","OpenLayers/Strategy.js","OpenLayers/Strategy/Fixed.js","OpenLayers/Strategy/Cluster.js","OpenLayers/Strategy/Paging.js","OpenLayers/Strategy/BBOX.js","OpenLayers/Strategy/Save.js","OpenLayers/Strategy/Refresh.js","OpenLayers/Filter.js","OpenLayers/Filter/FeatureId.js","OpenLayers/Filter/Logical.js","OpenLayers/Filter/Comparison.js","OpenLayers/Filter/Spatial.js","OpenLayers/Protocol.js","OpenLayers/Protocol/HTTP.js","OpenLayers/Protocol/SQL.js","OpenLayers/Protocol/SQL/Gears.js","OpenLayers/Protocol/WFS.js","OpenLayers/Protocol/WFS/v1.js","OpenLayers/Protocol/WFS/v1_0_0.js","OpenLayers/Protocol/WFS/v1_1_0.js","OpenLayers/Protocol/SOS.js","OpenLayers/Protocol/SOS/v1_0_0.js","OpenLayers/Layer/PointTrack.js","OpenLayers/Layer/GML.js","OpenLayers/Style.js","OpenLayers/StyleMap.js","OpenLayers/Rule.js","OpenLayers/Format.js","OpenLayers/Format/XML.js","OpenLayers/Format/ArcXML.js","OpenLayers/Format/ArcXML/Features.js","OpenLayers/Format/GML.js","OpenLayers/Format/GML/Base.js","OpenLayers/Format/GML/v2.js","OpenLayers/Format/GML/v3.js","OpenLayers/Format/Atom.js","OpenLayers/Format/KML.js","OpenLayers/Format/GeoRSS.js","OpenLayers/Format/WFS.js","OpenLayers/Format/WFSCapabilities.js","OpenLayers/Format/WFSCapabilities/v1.js","OpenLayers/Format/WFSCapabilities/v1_0_0.js","OpenLayers/Format/WFSCapabilities/v1_1_0.js","OpenLayers/Format/WFSDescribeFeatureType.js","OpenLayers/Format/WMSDescribeLayer.js","OpenLayers/Format/WMSDescribeLayer/v1_1.js","OpenLayers/Format/WKT.js","OpenLayers/Format/OSM.js","OpenLayers/Format/GPX.js","OpenLayers/Format/Filter.js","OpenLayers/Format/Filter/v1.js","OpenLayers/Format/Filter/v1_0_0.js","OpenLayers/Format/Filter/v1_1_0.js","OpenLayers/Format/SLD.js","OpenLayers/Format/SLD/v1.js","OpenLayers/Format/SLD/v1_0_0.js","OpenLayers/Format/CSWGetDomain.js","OpenLayers/Format/CSWGetDomain/v2_0_2.js","OpenLayers/Format/CSWGetRecords.js","OpenLayers/Format/CSWGetRecords/v2_0_2.js","OpenLayers/Format/WFST.js","OpenLayers/Format/WFST/v1.js","OpenLayers/Format/WFST/v1_0_0.js","OpenLayers/Format/WFST/v1_1_0.js","OpenLayers/Format/Text.js","OpenLayers/Format/JSON.js","OpenLayers/Format/GeoJSON.js","OpenLayers/Format/WMC.js","OpenLayers/Format/WMC/v1.js","OpenLayers/Format/WMC/v1_0_0.js","OpenLayers/Format/WMC/v1_1_0.js","OpenLayers/Format/WMSCapabilities.js","OpenLayers/Format/WMSCapabilities/v1.js","OpenLayers/Format/WMSCapabilities/v1_1.js","OpenLayers/Format/WMSCapabilities/v1_1_0.js","OpenLayers/Format/WMSCapabilities/v1_1_1.js","OpenLayers/Format/WMSCapabilities/v1_3.js","OpenLayers/Format/WMSCapabilities/v1_3_0.js","OpenLayers/Format/WMSGetFeatureInfo.js","OpenLayers/Format/OWSCommon/v1_1_0.js","OpenLayers/Format/SOSCapabilities.js","OpenLayers/Format/SOSCapabilities/v1_0_0.js","OpenLayers/Format/SOSGetObservation.js","OpenLayers/Format/SOSGetFeatureOfInterest.js","OpenLayers/Layer/WFS.js","OpenLayers/Control/GetFeature.js","OpenLayers/Control/MouseToolbar.js","OpenLayers/Control/NavToolbar.js","OpenLayers/Control/PanPanel.js","OpenLayers/Control/Pan.js","OpenLayers/Control/ZoomIn.js","OpenLayers/Control/ZoomOut.js","OpenLayers/Control/ZoomPanel.js","OpenLayers/Control/EditingToolbar.js","OpenLayers/Lang.js","OpenLayers/Lang/en.js");var agent=navigator.userAgent;var docWrite=(agent.match("MSIE")||agent.match("Safari"));if(docWrite){var allScriptTags=new Array(jsfiles.length);}
 var host=OpenLayers._getScriptLocation()+"lib/";for(var i=0,len=jsfiles.length;i<len;i++){if(docWrite){allScriptTags[i]="<script src='"+host+jsfiles[i]+"'></script>";}else{var s=document.createElement("script");s.src=host+jsfiles[i];var h=document.getElementsByTagName("head").length?document.getElementsByTagName("head")[0]:document.body;h.appendChild(s);}}
-if(docWrite){document.write(allScriptTags.join(""));}}})();OpenLayers.VERSION_NUMBER="$Revision: 10129 $";OpenLayers.String={startsWith:function(str,sub){return(str.indexOf(sub)==0);},contains:function(str,sub){return(str.indexOf(sub)!=-1);},trim:function(str){return str.replace(/^\s\s*/,'').replace(/\s\s*$/,'');},camelize:function(str){var oStringList=str.split('-');var camelizedString=oStringList[0];for(var i=1,len=oStringList.length;i<len;i++){var s=oStringList[i];camelizedString+=s.charAt(0).toUpperCase()+s.substring(1);}
+if(docWrite){document.write(allScriptTags.join(""));}}})();OpenLayers.VERSION_NUMBER="OpenLayers 2.9.1 -- $Revision: 10129 $";OpenLayers.String={startsWith:function(str,sub){return(str.indexOf(sub)==0);},contains:function(str,sub){return(str.indexOf(sub)!=-1);},trim:function(str){return str.replace(/^\s\s*/,'').replace(/\s\s*$/,'');},camelize:function(str){var oStringList=str.split('-');var camelizedString=oStringList[0];for(var i=1,len=oStringList.length;i<len;i++){var s=oStringList[i];camelizedString+=s.charAt(0).toUpperCase()+s.substring(1);}
 return camelizedString;},format:function(template,context,args){if(!context){context=window;}
 var replacer=function(str,match){var replacement;var subs=match.split(/\.+/);for(var i=0;i<subs.length;i++){if(i==0){replacement=context;}
 replacement=replacement[subs[i]];}
@@ -476,7 +476,7 @@ if(style.graphicWidth&&style.graphicHeight){node.setAttributeNS(null,"preserveAs
 var width=style.graphicWidth||style.graphicHeight;var height=style.graphicHeight||style.graphicWidth;width=width?width:style.pointRadius*2;height=height?height:style.pointRadius*2;var xOffset=(style.graphicXOffset!=undefined)?style.graphicXOffset:-(0.5*width);var yOffset=(style.graphicYOffset!=undefined)?style.graphicYOffset:-(0.5*height);var opacity=style.graphicOpacity||style.fillOpacity;node.setAttributeNS(null,"x",(pos.x+xOffset).toFixed());node.setAttributeNS(null,"y",(pos.y+yOffset).toFixed());node.setAttributeNS(null,"width",width);node.setAttributeNS(null,"height",height);node.setAttributeNS(this.xlinkns,"href",style.externalGraphic);node.setAttributeNS(null,"style","opacity: "+opacity);}else if(this.isComplexSymbol(style.graphicName)){var offset=style.pointRadius*3;var size=offset*2;var id=this.importSymbol(style.graphicName);pos=this.getPosition(node);widthFactor=this.symbolMetrics[id][0]*3/size;var parent=node.parentNode;var nextSibling=node.nextSibling;if(parent){parent.removeChild(node);}
 if(this.supportUse===false){var src=document.getElementById(id);node.firstChild&&node.removeChild(node.firstChild);node.appendChild(src.firstChild.cloneNode(true));node.setAttributeNS(null,"viewBox",src.getAttributeNS(null,"viewBox"));}else{node.setAttributeNS(this.xlinkns,"href","#"+id);}
 node.setAttributeNS(null,"width",size);node.setAttributeNS(null,"height",size);node.setAttributeNS(null,"x",pos.x-offset);node.setAttributeNS(null,"y",pos.y-offset);if(nextSibling){parent.insertBefore(node,nextSibling);}else if(parent){parent.appendChild(node);}}else{node.setAttributeNS(null,"r",style.pointRadius);}
-var rotation=style.rotation;if(node._rotation!==rotation&&pos){node._rotation=rotation;rotation|=0;if(node.nodeName!=="svg"){node.setAttributeNS(null,"transform","rotate("+rotation+" "+pos.x+" "+
+var rotation=style.rotation;if((rotation!==undefined||node._rotation!==undefined)&&pos){node._rotation=rotation;rotation|=0;if(node.nodeName!=="svg"){node.setAttributeNS(null,"transform","rotate("+rotation+" "+pos.x+" "+
 pos.y+")");}else{var metrics=this.symbolMetrics[id]
 node.firstChild.setAttributeNS(null,"transform","rotate("+style.rotation+" "+metrics[1]+" "+metrics[2]+")");}}}
 if(options.isFilled){node.setAttributeNS(null,"fill",style.fillColor);node.setAttributeNS(null,"fill-opacity",style.fillOpacity);}else{node.setAttributeNS(null,"fill","none");}
@@ -655,7 +655,8 @@ catch(e){}}
 popup.map=null;},getSize:function(){var size=null;if(this.size!=null){size=this.size.clone();}
 return size;},updateSize:function(){var newSize=this.getCurrentSize();if(newSize&&!isNaN(newSize.h)&&!isNaN(newSize.w)){this.events.clearMouseCache();var oldSize=this.getSize();if(oldSize==null){this.size=oldSize=newSize;}
 if(!newSize.equals(oldSize)){this.size=newSize;for(var i=0,len=this.layers.length;i<len;i++){this.layers[i].onMapResize();}
-var center=this.getCenter();if(this.baseLayer!=null&&center!=null){var zoom=this.getZoom();this.zoom=null;this.setCenter(center,zoom);}}}},getCurrentSize:function(){var size=new OpenLayers.Size(this.div.clientWidth,this.div.clientHeight);if(size.w==0&&size.h==0||isNaN(size.w)&&isNaN(size.h)){size.w=parseInt(this.div.style.width);size.h=parseInt(this.div.style.height);}
+var center=this.getCenter();if(this.baseLayer!=null&&center!=null){var zoom=this.getZoom();this.zoom=null;this.setCenter(center,zoom);}}}},getCurrentSize:function(){var size=new OpenLayers.Size(this.div.clientWidth,this.div.clientHeight);if(size.w==0&&size.h==0||isNaN(size.w)&&isNaN(size.h)){size.w=this.div.offsetWidth;size.h=this.div.offsetHeight;}
+if(size.w==0&&size.h==0||isNaN(size.w)&&isNaN(size.h)){size.w=parseInt(this.div.style.width);size.h=parseInt(this.div.style.height);}
 return size;},calculateBounds:function(center,resolution){var extent=null;if(center==null){center=this.getCenter();}
 if(resolution==null){resolution=this.getResolution();}
 if((center!=null)&&(resolution!=null)){var size=this.getSize();var w_deg=size.w*resolution;var h_deg=size.h*resolution;extent=new OpenLayers.Bounds(center.lon-w_deg/2,center.lat-h_deg/2,center.lon+w_deg/2,center.lat+h_deg/2);}
index 69bac58b5261ddd2ef93ada9d251a1a943e10aed..2590c2d5f655a3d456bb320c7447643884e9b83a 100644 (file)
@@ -562,6 +562,27 @@ hr {
   color: gray;
 }
 
+/* Rules for the user list */
+
+#user_list {
+  width: 100%;
+  font-size: small;
+}
+
+#user_list tr {
+  vertical-align: center;
+}
+
+#user_list p {
+  margin-top: 0px;
+  margin-bottom: 0px;
+}
+
+#user_list_actions {
+  float: right;
+  margin-top: 10px;
+}
+
 /* Rules for the account confirmation page */
 
 div#contributorTerms {
index 2e60d630f885e79423388d0f99b6e12803c9b563..4ceb92cfcc470bf22b74cc25e43c274eda99cfc0 100755 (executable)
@@ -16,7 +16,7 @@ puts "<h2>OpenStreetMap stats report run at #{start_time.to_s}</h2>"
 
 begin
   ActiveRecord::Base.transaction do
-    user_count = User.count(:conditions => "active = 1")
+    user_count = User.count(:conditions => { :status => ["active", "confirmed", "suspended"] })
     tracepoint_count = Tracepoint.count()
     node_count = Node.count(:conditions => "visible = true")
     way_count = Way.count(:conditions => "visible = true")
index 1849fd4d99aae8ddeb603e51f1d58786aa1e4be1..eb3c6ef6d590547fd78b029dd0be720a805a3749 100644 (file)
@@ -2,7 +2,7 @@
 normal_user:
   id: 1
   email: test@openstreetmap.org
-  active: true
+  status: active
   pass_crypt: <%= Digest::MD5.hexdigest('test') %>
   creation_time: "2007-01-01 00:00:00"
   display_name: test
@@ -15,7 +15,7 @@ normal_user:
 public_user:
   id: 2
   email: test@example.com
-  active: true
+  status: active
   pass_crypt: <%= Digest::MD5.hexdigest('test') %>
   creation_time: "2008-05-01 01:23:45"
   display_name: test2
@@ -28,7 +28,7 @@ public_user:
 inactive_user:
   id: 3
   email: inactive@openstreetmap.org
-  active: false
+  status: pending
   pass_crypt: <%= Digest::MD5::hexdigest('test2') %>
   creation_time: "2008-07-01 02:23:45"
   display_name: Inactive User
@@ -41,7 +41,7 @@ inactive_user:
 second_public_user:
   id: 4
   email: public@OpenStreetMap.org
-  active: true
+  status: active
   pass_crypt: <%= Digest::MD5.hexdigest('test') %>
   creation_time: "2008-05-01 01:23:45"
   display_name: pulibc_test2
@@ -54,7 +54,7 @@ second_public_user:
 moderator_user:
   id: 5
   email: moderator@example.com
-  active: true
+  status: active
   pass_crypt: <%= Digest::MD5.hexdigest('test') %>
   creation_time: "2008-05-01 01:23:45"
   display_name: moderator
@@ -63,7 +63,7 @@ moderator_user:
 administrator_user:
   id: 6
   email: administrator@example.com
-  active: true
+  status: active
   pass_crypt: <%= Digest::MD5.hexdigest('test') %>
   creation_time: "2008-05-01 01:23:45"
   display_name: administrator
index f1994f4ddbfc3ebcc7bbb04d6267ab811ae5fd6d..ac2bd5e7145997613879b21d3cf1dbc5439c761c 100644 (file)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 require File.dirname(__FILE__) + '/../test_helper'
 
 class UserTest < ActiveSupport::TestCase
@@ -18,7 +19,7 @@ class UserTest < ActiveSupport::TestCase
   
   def test_unique_email
     new_user = User.new(:email => users(:normal_user).email,
-      :active => 1
+      :status => "active"
       :pass_crypt => Digest::MD5.hexdigest('test'),
       :display_name => "new user",
       :data_public => 1,
@@ -29,7 +30,7 @@ class UserTest < ActiveSupport::TestCase
   
   def test_unique_display_name
     new_user = User.new(:email => "tester@openstreetmap.org",
-      :active => 0,
+      :status => "pending",
       :pass_crypt => Digest::MD5.hexdigest('test'),
       :display_name => users(:normal_user).display_name, 
       :data_public => 1,