Commit 30285ce6 authored by Eric Davis's avatar Eric Davis

Merge branch 'release-v2.1.0' into stable

parents effcd726 2d67c2f2
......@@ -26,4 +26,5 @@
doc/app
/.bundle
/Gemfile.lock
/Gemfile.local
/.rvmrc*
......@@ -11,6 +11,9 @@ group :test do
gem 'shoulda', '~> 2.10.3'
gem 'edavis10-object_daddy', :require => 'object_daddy'
gem 'mocha'
platforms :mri_18 do gem 'ruby-debug' end
platforms :mri_19 do gem 'ruby-debug19', :require => 'ruby-debug' end
end
group :openid do
......@@ -36,15 +39,22 @@ platforms :mri do
group :mysql2 do
gem "mysql2", "~> 0.2.7"
end
group :postgres do
gem "pg", "~> 0.9.0"
# gem "postgres-pr"
end
end
platforms :mri_18 do
group :sqlite do
gem "sqlite3-ruby", "< 1.3", :require => "sqlite3"
# please tell me, if you are fond of a pure ruby sqlite3 binding
end
end
platforms :mri_19 do
group :sqlite do
gem "sqlite3"
end
end
......@@ -54,16 +64,23 @@ platforms :jruby do
group :mysql do
gem "activerecord-jdbcmysql-adapter"
end
group :postgres do
gem "activerecord-jdbcpostgresql-adapter"
end
group :sqlite do
gem "activerecord-jdbcsqlite3-adapter"
end
end
# Load a "local" Gemfile
gemfile_local = File.join(File.dirname(__FILE__), "Gemfile.local")
if File.readable?(gemfile_local)
puts "Loading #{gemfile_local} ..." if $DEBUG
instance_eval(File.read(gemfile_local))
end
# Load plugins' Gemfiles
Dir.glob File.expand_path("../vendor/plugins/*/Gemfile", __FILE__) do |file|
puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v`
......
......@@ -24,6 +24,12 @@ class ApplicationController < ActionController::Base
layout 'base'
exempt_from_layout 'builder', 'rsb'
protect_from_forgery
def handle_unverified_request
super
cookies.delete(:autologin)
end
# Remove broken cookie after upgrade from 0.8.x (#4292)
# See https://rails.lighthouseapp.com/projects/8994/tickets/3360
# TODO: remove it when Rails is fixed
......@@ -38,7 +44,6 @@ class ApplicationController < ActionController::Base
before_filter :user_setup, :check_if_login_required, :set_localization
filter_parameter_logging :password
protect_from_forgery
rescue_from ActionController::InvalidAuthenticityToken, :with => :invalid_authenticity_token
......
......@@ -286,7 +286,7 @@ private
render_error l(:error_no_tracker_in_project)
return false
end
@issue.start_date ||= Date.today
@issue.start_date ||= User.current.today
if params[:issue].is_a?(Hash)
@issue.safe_attributes = params[:issue]
if User.current.allowed_to?(:add_issue_watchers, @project) && @issue.new_record?
......
......@@ -16,10 +16,12 @@ class ProjectsController < ApplicationController
menu_item :roadmap, :only => :roadmap
menu_item :settings, :only => :settings
before_filter :find_project, :except => [ :index, :list, :new, :create, :copy ]
before_filter :authorize, :except => [ :index, :list, :new, :create, :copy, :archive, :unarchive, :destroy]
before_filter :find_project, :except => [ :index, :new, :create, :copy ]
before_filter :authorize, :only => [ :show, :settings, :edit, :update, :modules ]
before_filter :authorize_global, :only => [:new, :create]
before_filter :require_admin, :only => [ :copy, :archive, :unarchive, :destroy ]
before_filter :jump_to_project_menu_item, :only => :show
before_filter :load_project_settings, :only => :settings
accept_key_auth :index, :show, :create, :update, :destroy
after_filter :only => [:create, :edit, :update, :archive, :unarchive, :destroy] do |controller|
......@@ -68,12 +70,7 @@ class ProjectsController < ApplicationController
if validate_parent_id && @project.save
@project.set_allowed_parent!(params[:project]['parent_id']) if params[:project].has_key?('parent_id')
# Add current user as a project member if he is not admin
unless User.current.admin?
r = Role.givable.find_by_id(Setting.new_project_user_role_id.to_i) || Role.givable.first
m = Member.new(:user => User.current, :roles => [r])
@project.members << m
end
add_current_user_to_project_if_not_admin(@project)
respond_to do |format|
format.html {
flash[:notice] = l(:notice_successful_create)
......@@ -128,11 +125,6 @@ class ProjectsController < ApplicationController
# Show @project
def show
if params[:jump]
# try to redirect to the requested menu item
redirect_to_project_menu_item(@project, params[:jump]) && return
end
@users_by_role = @project.users_by_role
@subprojects = @project.children.visible.all
@news = @project.news.find(:all, :limit => 5, :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC")
......@@ -151,8 +143,6 @@ class ProjectsController < ApplicationController
@total_hours = TimeEntry.visible.sum(:hours, :include => :project, :conditions => cond).to_f
end
@key = User.current.rss_key
respond_to do |format|
format.html
format.api
......@@ -160,12 +150,6 @@ class ProjectsController < ApplicationController
end
def settings
@issue_custom_fields = IssueCustomField.find(:all, :order => "#{CustomField.table_name}.position")
@issue_category ||= IssueCategory.new
@member ||= @project.members.new
@trackers = Tracker.all
@repository ||= @project.repository
@wiki ||= @project.wiki
end
def edit
......@@ -187,7 +171,7 @@ class ProjectsController < ApplicationController
else
respond_to do |format|
format.html {
settings
load_project_settings
render :action => 'settings'
}
format.api { render_validation_errors(@project) }
......@@ -230,8 +214,7 @@ class ProjectsController < ApplicationController
end
end
end
# hide project in layout
@project = nil
hide_project_in_layout
end
private
......@@ -257,4 +240,33 @@ private
end
true
end
def jump_to_project_menu_item
if params[:jump]
# try to redirect to the requested menu item
redirect_to_project_menu_item(@project, params[:jump]) && return
end
end
def load_project_settings
@issue_custom_fields = IssueCustomField.find(:all, :order => "#{CustomField.table_name}.position")
@issue_category ||= IssueCategory.new
@member ||= @project.members.new
@trackers = Tracker.all
@repository ||= @project.repository
@wiki ||= @project.wiki
end
def hide_project_in_layout
@project = nil
end
def add_current_user_to_project_if_not_admin(project)
unless User.current.admin?
r = Role.givable.find_by_id(Setting.new_project_user_role_id.to_i) || Role.givable.first
m = Member.new(:user => User.current, :roles => [r])
project.members << m
end
end
end
......@@ -143,7 +143,12 @@ class RepositoriesController < ApplicationController
return true if Redmine::MimeType.is_type?('text', path)
# Ruby 1.8.6 has a bug of integer divisions.
# http://apidock.com/ruby/v1_8_6_287/String/is_binary_data%3F
return false if ent.is_binary_data?
if ent.respond_to?("is_binary_data?") && ent.is_binary_data? # Ruby 1.8.x and <1.9.2
return false
elsif ent.respond_to?(:force_encoding) && (ent.dup.force_encoding("UTF-8") != ent.dup.force_encoding("BINARY") ) # Ruby 1.9.2
# TODO: need to handle edge cases of non-binary content that isn't UTF-8
return false
end
true
end
private :is_entry_text_data?
......
......@@ -81,7 +81,7 @@ module ApplicationHelper
subject = truncate(subject, :length => options[:truncate])
end
end
s = link_to "#{issue.tracker} ##{issue.id}", {:controller => "issues", :action => "show", :id => issue},
s = link_to "#{h(issue.tracker)} ##{issue.id}", {:controller => "issues", :action => "show", :id => issue},
:class => issue.css_classes,
:title => title
s << ": #{h subject}" if subject
......
......@@ -129,82 +129,6 @@ module IssuesHelper
out
end
def show_detail(detail, no_html=false)
case detail.property
when 'attr'
field = detail.prop_key.to_s.gsub(/\_id$/, "")
label = l(("field_" + field).to_sym)
case
when ['due_date', 'start_date'].include?(detail.prop_key)
value = format_date(detail.value.to_date) if detail.value
old_value = format_date(detail.old_value.to_date) if detail.old_value
when ['project_id', 'status_id', 'tracker_id', 'assigned_to_id', 'priority_id', 'category_id', 'fixed_version_id'].include?(detail.prop_key)
value = find_name_by_reflection(field, detail.value)
old_value = find_name_by_reflection(field, detail.old_value)
when detail.prop_key == 'estimated_hours'
value = "%0.02f" % detail.value.to_f unless detail.value.blank?
old_value = "%0.02f" % detail.old_value.to_f unless detail.old_value.blank?
when detail.prop_key == 'parent_id'
label = l(:field_parent_issue)
value = "##{detail.value}" unless detail.value.blank?
old_value = "##{detail.old_value}" unless detail.old_value.blank?
end
when 'cf'
custom_field = CustomField.find_by_id(detail.prop_key)
if custom_field
label = custom_field.name
value = format_value(detail.value, custom_field.field_format) if detail.value
old_value = format_value(detail.old_value, custom_field.field_format) if detail.old_value
end
when 'attachment'
label = l(:label_attachment)
end
call_hook(:helper_issues_show_detail_after_setting, {:detail => detail, :label => label, :value => value, :old_value => old_value })
label ||= detail.prop_key
value ||= detail.value
old_value ||= detail.old_value
unless no_html
label = content_tag('strong', label)
old_value = content_tag("i", h(old_value)) if detail.old_value
old_value = content_tag("strike", old_value) if detail.old_value and (!detail.value or detail.value.empty?)
if detail.property == 'attachment' && !value.blank? && a = Attachment.find_by_id(detail.prop_key)
# Link to the attachment if it has not been removed
value = link_to_attachment(a)
else
value = content_tag("i", h(value)) if value
end
end
if detail.property == 'attr' && detail.prop_key == 'description'
s = l(:text_journal_changed_no_detail, :label => label)
unless no_html
diff_link = link_to 'diff',
{:controller => 'journals', :action => 'diff', :id => detail.journal_id, :detail_id => detail.id},
:title => l(:label_view_diff)
s << " (#{ diff_link })"
end
s
elsif !detail.value.blank?
case detail.property
when 'attr', 'cf'
if !detail.old_value.blank?
l(:text_journal_changed, :label => label, :old => old_value, :new => value)
else
l(:text_journal_set_to, :label => label, :value => value)
end
when 'attachment'
l(:text_journal_added, :label => label, :value => value)
end
else
l(:text_journal_deleted, :label => label, :old => old_value)
end
end
# Find the name of an associated record stored in the field attribute
def find_name_by_reflection(field, id)
association = Issue.reflect_on_association(field.to_sym)
......
......@@ -48,7 +48,7 @@ module JournalsHelper
if d = journal.render_detail(detail)
content_tag("li", d)
end
end.compact
end.compact.join(' ')
end
end
......
......@@ -57,4 +57,14 @@ module SearchHelper
end
('<ul>' + links.map {|link| content_tag('li', link)}.join(' ') + '</ul>') unless links.empty?
end
def link_to_previous_search_page(pagination_previous_date)
link_to_content_update('&#171; ' + l(:label_previous),
params.merge(:previous => 1, :offset => pagination_previous_date.strftime("%Y%m%d%H%M%S")))
end
def link_to_next_search_page(pagination_next_date)
link_to_content_update(l(:label_next) + ' &#187;',
params.merge(:previous => nil, :offset => pagination_next_date.strftime("%Y%m%d%H%M%S")))
end
end
......@@ -17,10 +17,22 @@ class Change < ActiveRecord::Base
validates_presence_of :changeset_id, :action, :path
before_save :init_path
delegate :repository_encoding, :to => :changeset, :allow_nil => true, :prefix => true
def relative_path
changeset.repository.relative_path(path)
end
def path
# TODO: shouldn't access Changeset#to_utf8 directly
self.path = Changeset.to_utf8(read_attribute(:path), changeset_repository_encoding)
end
def from_path
# TODO: shouldn't access Changeset#to_utf8 directly
self.path = Changeset.to_utf8(read_attribute(:from_path), changeset_repository_encoding)
end
def init_path
self.path ||= ""
end
......
......@@ -74,6 +74,23 @@ class Changeset < ActiveRecord::Base
user || committer.to_s.split('<').first
end
# Delegate to a Repository's log encoding
def repository_encoding
if repository.present?
repository.repo_log_encoding
else
nil
end
end
# Committer of the Changeset
#
# Attribute reader for committer that encodes the committer string to
# the repository log encoding (e.g. UTF-8)
def committer
self.class.to_utf8(read_attribute(:committer), repository.repo_log_encoding)
end
def before_create
self.committer = self.class.to_utf8(self.committer, repository.repo_log_encoding)
self.comments = self.class.normalize_comments(self.comments, repository.repo_log_encoding)
......@@ -239,6 +256,7 @@ class Changeset < ActiveRecord::Base
private
# TODO: refactor to a standard helper method
def self.to_utf8(str, encoding)
return str if str.nil?
str.force_encoding("ASCII-8BIT") if str.respond_to?(:force_encoding)
......@@ -273,12 +291,6 @@ class Changeset < ActiveRecord::Base
end
str = txtar
end
# removes invalid UTF8 sequences
begin
Iconv.conv('UTF-8//IGNORE', 'UTF-8', str + ' ')[0..-3]
rescue Iconv::InvalidEncoding
# "UTF-8//IGNORE" is not supported on some OS
str
end
str
end
end
......@@ -23,9 +23,17 @@ class Journal < ActiveRecord::Base
# Make sure each journaled model instance only has unique version ids
validates_uniqueness_of :version, :scope => [:journaled_id, :type]
belongs_to :journaled, :touch => true
# Define a default class_name to prevent `uninitialized constant Journal::Journaled`
# subclasses will be given an actual class name when they are created by aaj
#
# e.g. IssueJournal will get :class_name => 'Issue'
belongs_to :journaled, :class_name => 'Journal'
belongs_to :user
# "touch" the journaled object on creation
after_create :touch_journaled_after_creation
# ActiveRecord::Base#changes is an existing method, so before serializing the +changes+ column,
# the existing +changes+ method is undefined. The overridden +changes+ method pertained to
# dirty attributes, but will not affect the partial updates functionality as that's based on
......@@ -33,6 +41,10 @@ class Journal < ActiveRecord::Base
# undef_method :changes
serialize :changes, Hash
def touch_journaled_after_creation
journaled.touch
end
# In conjunction with the included Comparable module, allows comparison of journal records
# based on their corresponding version numbers, creation timestamps and IDs.
def <=>(other)
......
......@@ -185,7 +185,7 @@ class Mailer < ActionMailer::Base
cc((message.root.watcher_recipients + message.board.watcher_recipients).uniq - @recipients)
subject "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}"
body :message => message,
:message_url => url_for(message.last_journal.event_url)
:message_url => url_for({ :controller => 'messages', :action => 'show', :board_id => message.board, :id => message.root, :r => message, :anchor => "message-#{message.id}" })
render_multipart('message_posted', body)
end
......
......@@ -12,10 +12,7 @@
#++
class MessageObserver < ActiveRecord::Observer
def after_save(message)
if message.last_journal.version == 1
# Only deliver mails for the first journal
Mailer.deliver_message_posted(message) if Setting.notified_events.include?('message_posted')
end
def after_create(message)
Mailer.deliver_message_posted(message) if Setting.notified_events.include?('message_posted')
end
end
......@@ -126,8 +126,9 @@ class Query < ActiveRecord::Base
QueryColumn.new(:updated_on, :sortable => "#{Issue.table_name}.updated_on", :default_order => 'desc'),
QueryColumn.new(:category, :sortable => "#{IssueCategory.table_name}.name", :groupable => true),
QueryColumn.new(:fixed_version, :sortable => ["#{Version.table_name}.effective_date", "#{Version.table_name}.name"], :default_order => 'desc', :groupable => true),
QueryColumn.new(:start_date, :sortable => "#{Issue.table_name}.start_date"),
QueryColumn.new(:due_date, :sortable => "#{Issue.table_name}.due_date"),
# Put empty start_dates and due_dates in the far future rather than in the far past
QueryColumn.new(:start_date, :sortable => ["CASE WHEN #{Issue.table_name}.start_date IS NULL THEN 1 ELSE 0 END", "#{Issue.table_name}.start_date"]),
QueryColumn.new(:due_date, :sortable => ["CASE WHEN #{Issue.table_name}.due_date IS NULL THEN 1 ELSE 0 END", "#{Issue.table_name}.due_date"]),
QueryColumn.new(:estimated_hours, :sortable => "#{Issue.table_name}.estimated_hours"),
QueryColumn.new(:done_ratio, :sortable => "#{Issue.table_name}.done_ratio", :groupable => true),
QueryColumn.new(:created_on, :sortable => "#{Issue.table_name}.created_on", :default_order => 'desc'),
......@@ -587,9 +588,17 @@ class Query < ActiveRecord::Base
sql = "#{db_table}.#{db_field} IS NOT NULL"
sql << " AND #{db_table}.#{db_field} <> ''" if is_custom_filter
when ">="
sql = "#{db_table}.#{db_field} >= #{value.first.to_i}"
if is_custom_filter
sql = "#{db_table}.#{db_field} != '' AND CAST(#{db_table}.#{db_field} AS decimal(60,4)) >= #{value.first.to_f}"
else
sql = "#{db_table}.#{db_field} >= #{value.first.to_f}"
end
when "<="
sql = "#{db_table}.#{db_field} <= #{value.first.to_i}"
if is_custom_filter
sql = "#{db_table}.#{db_field} != '' AND CAST(#{db_table}.#{db_field} AS decimal(60,4)) <= #{value.first.to_f}"
else
sql = "#{db_table}.#{db_field} <= #{value.first.to_f}"
end
when "o"
sql = "#{IssueStatus.table_name}.is_closed=#{connection.quoted_false}" if field == "status_id"
when "c"
......@@ -629,6 +638,8 @@ class Query < ActiveRecord::Base
custom_fields.select(&:is_filter?).each do |field|
case field.field_format
when "int", "float"
options = { :type => :integer, :order => 20 }
when "text"
options = { :type => :text, :order => 20 }
when "list"
......
......@@ -59,12 +59,7 @@ class WikiContent < ActiveRecord::Base
end
def version
unless last_journal
# FIXME: This is code that caters for a case that should never happen in the normal code paths!!
create_journal
last_journal.update_attribute(:created_at, updated_on)
end
last_journal.version
new_record? ? 0 : last_journal.version
end
private
......@@ -106,9 +101,9 @@ class WikiContent < ActiveRecord::Base
end
def text
@text ||= case changes[:compression]
when 'gzip'
Zlib::Inflate.inflate(data)
@text ||= case changes["compression"]
when "gzip"
Zlib::Inflate.inflate(changes["data"])
else
# uncompressed data
changes["data"]
......
<%= render :partial => 'action_menu' %>
<h2><%= @issue.tracker.name %> #<%= @issue.id %><%= call_hook(:view_issues_show_identifier, :issue => @issue) %></h2>
<h2><%= h(@issue.tracker.name) %> #<%= h(@issue.id) %><%= call_hook(:view_issues_show_identifier, :issue => @issue) %></h2>
<div class="<%= @issue.css_classes %> details">
<%= avatar(@issue.author, :size => "50") %>
......@@ -17,11 +17,11 @@
<table class="attributes">
<tr>
<th class="status"><%=l(:field_status)%>:</th><td class="status"><%= @issue.status.name %></td>
<th class="status"><%=l(:field_status)%>:</th><td class="status"><%= h(@issue.status.name) %></td>
<th class="start-date"><%=l(:field_start_date)%>:</th><td class="start-date"><%= format_date(@issue.start_date) %></td>
</tr>
<tr>
<th class="priority"><%=l(:field_priority)%>:</th><td class="priority"><%= @issue.priority.name %></td>
<th class="priority"><%=l(:field_priority)%>:</th><td class="priority"><%= h(@issue.priority.name) %></td>
<th class="due-date"><%=l(:field_due_date)%>:</th><td class="due-date"><%= format_date(@issue.due_date) %></td>
</tr>
<tr>
......@@ -29,7 +29,7 @@
<th class="progress"><%=l(:field_done_ratio)%>:</th><td class="progress"><%= progress_bar @issue.done_ratio, :width => '80px', :legend => "#{@issue.done_ratio}%" %></td>
</tr>
<tr>
<th class="category"><%=l(:field_category)%>:</th><td class="category"><%=h @issue.category ? @issue.category.name : "-" %></td>
<th class="category"><%=l(:field_category)%>:</th><td class="category"><%=h(@issue.category ? @issue.category.name : "-") %></td>
<% if User.current.allowed_to?(:view_time_entries, @project) %>
<th class="spent-time"><%=l(:label_spent_time)%>:</th>
<td class="spent-time"><%= @issue.spent_hours > 0 ? (link_to l_hours(@issue.spent_hours), {:controller => 'timelog', :action => 'index', :project_id => @project, :issue_id => @issue}) : "-" %></td>
......
......@@ -22,6 +22,6 @@
<td class="revision"><%= link_to_revision(changeset, @project) if changeset %></td>
<td class="age"><%= distance_of_time_in_words(entry.lastrev.time, Time.now) if entry.lastrev && entry.lastrev.time %></td>
<td class="author"><%= changeset.nil? ? h(replace_invalid_utf8(entry.lastrev.author.to_s.split('<').first)) : changeset.author if entry.lastrev %></td>
<td class="comments"><%=h truncate(changeset.comments, :length => 50) unless changeset.nil? %></td>
<td class="comments"><%=h truncate(Changeset.to_utf8(changeset.comments, changeset.repository.repo_log_encoding), :length => 50) unless changeset.nil? %></td>
</tr>
<% end %>
......@@ -18,7 +18,7 @@
<td class="checkbox"><%= radio_button_tag('rev_to', changeset.identifier, (line_num==2), :id => "cbto-#{line_num}", :onclick => "if ($('cb-#{line_num}').checked==true) {$('cb-#{line_num-1}').checked=true;}") if show_diff && (line_num > 1) %></td>
<td class="committed_on"><%= format_time(changeset.committed_on) %></td>
<td class="author"><%=h changeset.author %></td>
<td class="comments"><%= textilizable(truncate_at_line_break(changeset.comments)) %></td>
<td class="comments"><%= textilizable(truncate_at_line_break(Changeset.to_utf8(changeset.comments, changeset.repository.repo_log_encoding))) %></td>
</tr>
<% line_num += 1 %>
<% end %>
......
<div class="search-pagination">
<p>
<% if pagination_previous_date %>
<%= link_to_previous_search_page(pagination_previous_date) %>
<% end %>
<% if pagination_next_date %>
<%= link_to_next_search_page(pagination_next_date) %>
<% end %>
</p>
</div>
......@@ -24,6 +24,9 @@
</div>
<h3><%= l(:label_result_plural) %> (<%= @results_by_type.values.sum %>)</h3>
<%= render :partial => 'pagination', :locals => {:pagination_previous_date => @pagination_previous_date, :pagination_next_date => @pagination_next_date } %>
<dl id="search-results">
<% @results.each do |e| %>
<dt class="<%= e.event_type %>">
......@@ -36,15 +39,6 @@
</dl>
<% end %>
<p><center>
<% if @pagination_previous_date %>
<%= link_to_content_update('&#171; ' + l(:label_previous),
params.merge(:previous => 1, :offset => @pagination_previous_date.strftime("%Y%m%d%H%M%S"))) %>&nbsp;
<% end %>
<% if @pagination_next_date %>
<%= link_to_content_update(l(:label_next) + ' &#187;',
params.merge(:previous => nil, :offset => @pagination_next_date.strftime("%Y%m%d%H%M%S"))) %>
<% end %>
</center></p>
<%= render :partial => 'pagination', :locals => {:pagination_previous_date => @pagination_previous_date, :pagination_next_date => @pagination_next_date } %>
<% html_title(l(:label_search)) -%>
......@@ -3,6 +3,7 @@
<head>
<title><%=h @page.pretty_title %></title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<base href="<%= "#{h Setting.protocol}://#{h Setting.host_name}" %>" />
<style>
body { font:80% Verdana,Tahoma,Arial,sans-serif; }
h1, h2, h3, h4 { font-family: "Trebuchet MS",Georgia,"Times New Roman",serif; }
......@@ -16,6 +17,6 @@ h1:hover a.wiki-anchor, h2:hover a.wiki-anchor, h3:hover a.wiki-anchor { display
</style>
</head>
<body>
<%= textilizable @content, :text, :wiki_links => :local %>
<%= textilizable @content, :text, :wiki_links => :local, :only_path => false %>
</body>
</html>
......@@ -945,21 +945,21 @@ bg:
enumeration_activities: Дейности (time tracking)
enumeration_system_activity: Системна активност
text_powered_by: Powered by %{link}
label_cvs_module: Module
label_filesystem_path: Root directory
label_darcs_path: Root directory
label_bazaar_path: Root directory
text_powered_by: Този сайт е задвижван от %{link}
label_cvs_module: Модул
label_filesystem_path: Коренна директория
label_darcs_path: Коренна директория
label_bazaar_path: Коренна директория
label_cvs_path: CVSROOT
label_git_path: Path to .git directory
label_mercurial_path: Root directory
label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee
button_expand_all: Expand all
button_collapse_all: Collapse all
label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author
field_effective_date: Due date
text_default_encoding: "Default: UTF-8"
label_git_path: Път до директория .git
label_mercurial_path: Коренна директория
label_additional_workflow_transitions_for_assignee: Позволени са допълнителни преходи, когато потребителят е назначеният към задачата
button_expand_all: Разгъване всички
button_collapse_all: Скриване всички
label_additional_workflow_transitions_for_author: Позволени са допълнителни преходи, когато потребителят е авторът
field_effective_date: Дата
text_default_encoding: "По подразбиране: UTF-8"
text_git_repo_example: a bare and local repository (e.g. /gitrepo, c:\gitrepo)
label_notify_member_plural: Email issue updates
label_path_encoding: Path encoding
text_mercurial_repo_example: local repository (e.g. /hgrepo, c:\hgrepo)
label_path_encoding: Кодиране на пътищата
text_mercurial_repo_example: локално хранилище (например /hgrepo, c:\hgrepo)