timelogging.patch
| db/migrate/095_add_start_and_end_time_to_time_entries.rb (revision 0) | ||
|---|---|---|
| 1 |
class AddStartAndEndTimeToTimeEntries < ActiveRecord::Migration |
|
| 2 |
def self.up |
|
| 3 |
add_column :time_entries, :start_time, :datetime |
|
| 4 |
add_column :time_entries, :end_time, :datetime |
|
| 5 |
end |
|
| 6 |
|
|
| 7 |
def self.down |
|
| 8 |
remove_column :time_entries, :start_time |
|
| 9 |
remove_column :time_entries, :end_time |
|
| 10 |
end |
|
| 11 |
end |
|
| db/migrate/096_allow_null_time_entry_hours.rb (revision 0) | ||
|---|---|---|
| 1 |
class AllowNullTimeEntryHours < ActiveRecord::Migration |
|
| 2 |
def self.up |
|
| 3 |
change_column :time_entries, :hours, :float, :null => true |
|
| 4 |
end |
|
| 5 |
|
|
| 6 |
def self.down |
|
| 7 |
# not needed |
|
| 8 |
end |
|
| 9 |
end |
|
| app/views/issues/_edit.rhtml (working copy) | ||
|---|---|---|
| 1 |
<% content_for :header_tags do %> |
|
| 2 |
<%= javascript_include_tag 'time' %> |
|
| 3 |
<% end %> |
|
| 1 | 4 |
<% labelled_tabular_form_for :issue, @issue, |
| 2 | 5 |
:url => {:action => 'edit', :id => @issue},
|
| 3 | 6 |
:html => {:id => 'issue-form',
|
| ... | ... | |
| 18 | 21 |
<% if authorize_for('timelog', 'edit') %>
|
| 19 | 22 |
<fieldset class="tabular"><legend><%= l(:button_log_time) %></legend> |
| 20 | 23 |
<% fields_for :time_entry, @time_entry, { :builder => TabularFormBuilder, :lang => current_language} do |time_entry| %>
|
| 24 |
<%= time_entry.hidden_field :id %> |
|
| 21 | 25 |
<div class="splitcontentleft"> |
| 22 | 26 |
<p><%= time_entry.text_field :hours, :size => 6, :label => :label_spent_time %> <%= l(:field_hours) %></p> |
| 27 |
<p><%= time_entry.time_field :start_time %></p> |
|
| 23 | 28 |
</div> |
| 24 | 29 |
<div class="splitcontentright"> |
| 25 | 30 |
<p><%= time_entry.select :activity_id, activity_collection_for_select_options %></p> |
| 31 |
<p><%= time_entry.time_field :end_time %></p> |
|
| 26 | 32 |
</div> |
| 27 | 33 |
<p><%= time_entry.text_field :comments, :size => 60 %></p> |
| 28 | 34 |
<% end %> |
| app/views/issues/show.rhtml (working copy) | ||
|---|---|---|
| 33 | 33 |
<td><b><%=l(:field_category)%>:</b></td><td><%=h @issue.category ? @issue.category.name : "-" %></td> |
| 34 | 34 |
<% if User.current.allowed_to?(:view_time_entries, @project) %> |
| 35 | 35 |
<td><b><%=l(:label_spent_time)%>:</b></td> |
| 36 |
<td><%= @issue.spent_hours > 0 ? (link_to lwr(:label_f_hour, @issue.spent_hours), {:controller => 'timelog', :action => 'details', :project_id => @project, :issue_id => @issue}, :class => 'icon icon-time') : "-" %></td>
|
|
| 36 |
<td><%= spent_hours(@issue) %></td> |
|
| 37 | 37 |
<% end %> |
| 38 | 38 |
</tr> |
| 39 | 39 |
<tr> |
| app/views/timelog/_list.rhtml (working copy) | ||
|---|---|---|
| 2 | 2 |
<thead> |
| 3 | 3 |
<tr> |
| 4 | 4 |
<%= sort_header_tag('spent_on', :caption => l(:label_date), :default_order => 'desc') %>
|
| 5 |
<%= sort_header_tag('start_time', :caption => l(:field_start_time), :default_order => 'desc') %>
|
|
| 6 |
<%= sort_header_tag('end_time', :caption => l(:field_end_time), :default_order => 'desc') %>
|
|
| 7 |
<%= sort_header_tag('hours', :caption => l(:field_hours)) %>
|
|
| 5 | 8 |
<%= sort_header_tag('user_id', :caption => l(:label_member)) %>
|
| 6 | 9 |
<%= sort_header_tag('activity_id', :caption => l(:label_activity)) %>
|
| 7 | 10 |
<%= sort_header_tag("#{Project.table_name}.name", :caption => l(:label_project)) %>
|
| 8 | 11 |
<%= sort_header_tag('issue_id', :caption => l(:label_issue), :default_order => 'desc') %>
|
| 9 | 12 |
<th><%= l(:field_comments) %></th> |
| 10 |
<%= sort_header_tag('hours', :caption => l(:field_hours)) %>
|
|
| 11 | 13 |
<th></th> |
| 12 | 14 |
</tr> |
| 13 | 15 |
</thead> |
| ... | ... | |
| 15 | 17 |
<% entries.each do |entry| -%> |
| 16 | 18 |
<tr class="time-entry <%= cycle("odd", "even") %>">
|
| 17 | 19 |
<td class="spent_on"><%= format_date(entry.spent_on) %></td> |
| 20 |
<td class="start_time"><%= format_time(entry.start_time) %></td> |
|
| 21 |
<td class="end_time"><%= format_time(entry.end_time) %></td> |
|
| 22 |
<td class="hours"><%= hours(entry) %></td> |
|
| 18 | 23 |
<td class="user"><%=h entry.user %></td> |
| 19 | 24 |
<td class="activity"><%=h entry.activity %></td> |
| 20 | 25 |
<td class="project"><%=h entry.project %></td> |
| ... | ... | |
| 24 | 29 |
<% end -%> |
| 25 | 30 |
</td> |
| 26 | 31 |
<td class="comments"><%=h entry.comments %></td> |
| 27 |
<td class="hours"><%= html_hours("%.2f" % entry.hours) %></td>
|
|
| 28 | 32 |
<td align="center"> |
| 29 | 33 |
<% if entry.editable_by?(User.current) -%> |
| 30 | 34 |
<%= link_to image_tag('edit.png'), {:controller => 'timelog', :action => 'edit', :id => entry},
|
| app/views/timelog/edit.rhtml (working copy) | ||
|---|---|---|
| 3 | 3 |
<% labelled_tabular_form_for :time_entry, @time_entry, :url => {:action => 'edit', :project_id => @time_entry.project} do |f| %>
|
| 4 | 4 |
<%= error_messages_for 'time_entry' %> |
| 5 | 5 |
<%= back_url_hidden_field_tag %> |
| 6 |
<% content_for :header_tags do %> |
|
| 7 |
<%= javascript_include_tag 'time' %> |
|
| 8 |
<% end %> |
|
| 6 | 9 |
|
| 10 |
<% content_for :header_tags do %> |
|
| 11 |
<script language="javascript"> |
|
| 12 |
window.onload = function() {
|
|
| 13 |
$('<%= @activate_field %>').activate();
|
|
| 14 |
}; |
|
| 15 |
</script> |
|
| 16 |
<% end %> |
|
| 17 |
|
|
| 7 | 18 |
<div class="box"> |
| 8 | 19 |
<p><%= f.text_field :issue_id, :size => 6 %> <em><%= h("#{@time_entry.issue.tracker.name} ##{@time_entry.issue.id}: #{@time_entry.issue.subject}") if @time_entry.issue %></em></p>
|
| 9 | 20 |
<p><%= f.text_field :spent_on, :size => 10, :required => true %><%= calendar_for('time_entry_spent_on') %></p>
|
| 10 |
<p><%= f.text_field :hours, :size => 6, :required => true %></p> |
|
| 21 |
<p><%= f.time_field :start_time %></p> |
|
| 22 |
<p><%= f.time_field :end_time %></p> |
|
| 23 |
<p><%= f.text_field :hours, :size => 6 %> <em> <%= l(:text_clear_to_recalculate_time_by_range) %></em> </p> |
|
| 11 | 24 |
<p><%= f.text_field :comments, :size => 100 %></p> |
| 12 | 25 |
<p><%= f.select :activity_id, activity_collection_for_select_options, :required => true %></p> |
| 13 | 26 |
</div> |
| lib/tabular_form_builder.rb (working copy) | ||
|---|---|---|
| 40 | 40 |
END_SRC |
| 41 | 41 |
class_eval src, __FILE__, __LINE__ |
| 42 | 42 |
end |
| 43 |
|
|
| 44 |
def time_field(field) |
|
| 45 |
value = nil |
|
| 46 |
value = @object.send(field) if @object |
|
| 47 |
value = value.strftime('%Y-%m-%d %H:%M') if value
|
|
| 48 |
result = text_field field, :size => 15, :value => value |
|
| 49 |
result += (' <input type="button" onclick="maybeSetTimeNow($(\'%s\'))' +
|
|
| 50 |
'" value="' + l(:button_now) + |
|
| 51 |
'" name="action"/>') % "#{@object_name}_#{field}"
|
|
| 52 |
result |
|
| 53 |
end |
|
| 43 | 54 |
|
| 44 | 55 |
def select(field, choices, options = {}, html_options = {})
|
| 45 | 56 |
label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "")
|
| app/controllers/application.rb (working copy) | ||
|---|---|---|
| 219 | 219 |
def filename_for_content_disposition(name) |
| 220 | 220 |
request.env['HTTP_USER_AGENT'] =~ %r{MSIE} ? ERB::Util.url_encode(name) : name
|
| 221 | 221 |
end |
| 222 |
|
|
| 223 |
def url_path(url_parameters) |
|
| 224 |
rs = ::ActionController::Routing::Routes |
|
| 225 |
rs.generate url_parameters |
|
| 226 |
end |
|
| 222 | 227 |
end |
| app/controllers/issues_controller.rb (working copy) | ||
|---|---|---|
| 101 | 101 |
@allowed_statuses = @issue.new_statuses_allowed_to(User.current) |
| 102 | 102 |
@edit_allowed = User.current.allowed_to?(:edit_issues, @project) |
| 103 | 103 |
@priorities = Enumeration::get_values('IPRI')
|
| 104 |
@time_entry = TimeEntry.new |
|
| 104 |
@time_entry = @issue.time_entry_in_progress(User.current) || TimeEntry.new |
|
| 105 | 105 |
respond_to do |format| |
| 106 | 106 |
format.html { render :template => 'issues/show.rhtml' }
|
| 107 | 107 |
format.atom { render :action => 'changes', :layout => false, :content_type => 'application/atom+xml' }
|
| ... | ... | |
| 172 | 172 |
end |
| 173 | 173 |
|
| 174 | 174 |
if request.post? |
| 175 |
@time_entry = TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => Date.today) |
|
| 175 |
@time_entry = TimeEntry.find_by_id(params[:time_entry][:id]) if params[:time_entry] |
|
| 176 |
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, |
|
| 177 |
:user => User.current, :spent_on => Date.today) |
|
| 178 |
|
|
| 176 | 179 |
@time_entry.attributes = params[:time_entry] |
| 177 | 180 |
attachments = attach_files(@issue, params[:attachments]) |
| 178 | 181 |
attachments.each {|a| journal.details << JournalDetail.new(:property => 'attachment', :prop_key => a.id, :value => a.filename)}
|
| app/controllers/timelog_controller.rb (working copy) | ||
|---|---|---|
| 175 | 175 |
end |
| 176 | 176 |
|
| 177 | 177 |
def edit |
| 178 |
return if redirect_if_in_progress |
|
| 179 |
|
|
| 178 | 180 |
render_403 and return if @time_entry && !@time_entry.editable_by?(User.current) |
| 179 | 181 |
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => Date.today) |
| 180 | 182 |
@time_entry.attributes = params[:time_entry] |
| 183 |
if !@time_entry.hours |
|
| 184 |
if !@time_entry.start_time |
|
| 185 |
@activate_field = 'time_entry_start_time' |
|
| 186 |
else |
|
| 187 |
@activate_field = 'time_entry_end_time' |
|
| 188 |
end |
|
| 189 |
end |
|
| 190 |
|
|
| 191 |
url_writer = lambda do |entry| |
|
| 192 |
"<a href = \"#{url_path(:controller => :timelog, :action => :edit,
|
|
| 193 |
:id => entry.id)}\">##{entry.issue_id}-#{entry.id}</a>"
|
|
| 194 |
end |
|
| 195 |
|
|
| 181 | 196 |
if request.post? and @time_entry.save |
| 182 |
flash[:notice] = l(:notice_successful_update) |
|
| 197 |
intersecting = @time_entry.find_intersecting_entries |
|
| 198 |
logger.debug "intersecting = #{intersecting.inspect}"
|
|
| 199 |
msg = l(:notice_successful_update) |
|
| 200 |
if !intersecting.empty? |
|
| 201 |
|
|
| 202 |
list = lwr(:text_time_entry_intersecting_notice_entry, |
|
| 203 |
intersecting.size) + ' ' + intersecting. |
|
| 204 |
map { |entry| url_writer.call(entry) }.
|
|
| 205 |
to_sentence(:skip_last_comma => true, :connector => l(:text_and)) |
|
| 206 |
|
|
| 207 |
msg += ' ' + l(:text_time_entry_intersecting_notice, |
|
| 208 |
url_writer.call(@time_entry), list) |
|
| 209 |
end |
|
| 210 |
flash[:notice] = msg |
|
| 183 | 211 |
redirect_to(params[:back_url].blank? ? {:action => 'details', :project_id => @time_entry.project} : params[:back_url])
|
| 184 | 212 |
return |
| 185 | 213 |
end |
| ... | ... | |
| 258 | 286 |
@from ||= (TimeEntry.minimum(:spent_on, :include => :project, :conditions => @project.project_condition(Setting.display_subprojects_issues?)) || Date.today) - 1 |
| 259 | 287 |
@to ||= (TimeEntry.maximum(:spent_on, :include => :project, :conditions => @project.project_condition(Setting.display_subprojects_issues?)) || Date.today) |
| 260 | 288 |
end |
| 289 |
|
|
| 290 |
def redirect_if_in_progress |
|
| 291 |
if !@time_entry && @issue |
|
| 292 |
in_progress_entry = @issue.time_entry_in_progress(User.current) |
|
| 293 |
if in_progress_entry |
|
| 294 |
#in order to avoid :id form parameter and not complicate :find_project filter |
|
| 295 |
redirect_to(:controller => 'timelog', :action => 'edit', |
|
| 296 |
:id => in_progress_entry) |
|
| 297 |
return true |
|
| 298 |
end |
|
| 299 |
end |
|
| 300 |
false |
|
| 301 |
end |
|
| 261 | 302 |
end |
| app/helpers/application_helper.rb (working copy) | ||
|---|---|---|
| 70 | 70 |
@date_format ||= (Setting.date_format.blank? || Setting.date_format.size < 2 ? l(:general_fmt_date) : Setting.date_format) |
| 71 | 71 |
date.strftime(@date_format) |
| 72 | 72 |
end |
| 73 |
|
|
| 73 |
|
|
| 74 | 74 |
def format_time(time, include_date = true) |
| 75 | 75 |
return nil unless time |
| 76 | 76 |
time = time.to_time if time.is_a?(String) |
| ... | ... | |
| 78 | 78 |
local = zone ? time.in_time_zone(zone) : (time.utc? ? time.utc_to_local : time) |
| 79 | 79 |
@date_format ||= (Setting.date_format.blank? || Setting.date_format.size < 2 ? l(:general_fmt_date) : Setting.date_format) |
| 80 | 80 |
@time_format ||= (Setting.time_format.blank? ? l(:general_fmt_time) : Setting.time_format) |
| 81 |
include_date ? local.strftime("#{@date_format} #{@time_format}") : local.strftime(@time_format)
|
|
| 81 |
format = include_date ? "#{@date_format} #{@time_format}" : @time_format
|
|
| 82 |
local.strftime(format) |
|
| 82 | 83 |
end |
| 83 | 84 |
|
| 84 | 85 |
# Truncates and returns the string as a single line |
| app/helpers/issues_helper.rb (working copy) | ||
|---|---|---|
| 181 | 181 |
export.rewind |
| 182 | 182 |
export |
| 183 | 183 |
end |
| 184 |
|
|
| 185 |
def spent_hours(issue) |
|
| 186 |
return '-' if issue.time_entries.empty? |
|
| 187 |
spent_hours = lwr(:label_f_hour, issue.spent_hours) |
|
| 188 |
spent_hours += " (#{l(:text_in_progress)})" if issue.time_entry_in_progress
|
|
| 189 |
link_to spent_hours, {:controller => 'timelog', :action => 'details', :project_id => issue.project, :issue_id => issue}, :class => 'icon icon-time'
|
|
| 190 |
end |
|
| 184 | 191 |
end |
| app/helpers/timelog_helper.rb (working copy) | ||
|---|---|---|
| 36 | 36 |
sum |
| 37 | 37 |
end |
| 38 | 38 |
|
| 39 |
def hours(entry) |
|
| 40 |
return '<span class="hours hours-dec">[%s]</span>' % l(:text_in_progress) if !entry.hours |
|
| 41 |
html_hours("%.2f" % entry.hours)
|
|
| 42 |
end |
|
| 43 |
|
|
| 39 | 44 |
def options_for_period_select(value) |
| 40 | 45 |
options_for_select([[l(:label_all_time), 'all'], |
| 41 | 46 |
[l(:label_today), 'today'], |
| app/models/issue.rb (working copy) | ||
|---|---|---|
| 28 | 28 |
has_many :journals, :as => :journalized, :dependent => :destroy |
| 29 | 29 |
has_many :attachments, :as => :container, :dependent => :destroy |
| 30 | 30 |
has_many :time_entries, :dependent => :delete_all |
| 31 |
|
|
| 31 | 32 |
has_and_belongs_to_many :changesets, :order => "#{Changeset.table_name}.committed_on ASC, #{Changeset.table_name}.id ASC"
|
| 32 | 33 |
|
| 33 | 34 |
has_many :relations_from, :class_name => 'IssueRelation', :foreign_key => 'issue_from_id', :dependent => :delete_all |
| ... | ... | |
| 251 | 252 |
def to_s |
| 252 | 253 |
"#{tracker} ##{id}: #{subject}"
|
| 253 | 254 |
end |
| 255 |
|
|
| 256 |
def time_entry_in_progress(user = nil) |
|
| 257 |
TimeEntry.find_by_issue_id(self.id, |
|
| 258 |
:conditions => 'start_time IS NOT NULL and hours IS NULL' + (user ? " and user_id = #{user.id}" : ''))
|
|
| 259 |
end |
|
| 254 | 260 |
end |
| app/models/time_entry.rb (working copy) | ||
|---|---|---|
| 25 | 25 |
|
| 26 | 26 |
attr_protected :project_id, :user_id, :tyear, :tmonth, :tweek |
| 27 | 27 |
|
| 28 |
acts_as_event :title => Proc.new {|o| "#{o.user}: #{lwr(:label_f_hour, o.hours)} (#{(o.issue || o.project).event_title})"},
|
|
| 29 |
:url => Proc.new {|o| {:controller => 'timelog', :action => 'details', :project_id => o.project}},
|
|
| 28 |
title_proc = Proc.new do |entry| |
|
| 29 |
hours = entry.hours ? lwr(:label_f_hour, entry.hours) : "[#{l(:text_in_progress)}]"
|
|
| 30 |
"#{entry.user}: #{hours} (#{(entry.issue || entry.project).event_title})"
|
|
| 31 |
end |
|
| 32 |
|
|
| 33 |
acts_as_event :title => title_proc, |
|
| 34 |
:url => Proc.new {|entry| {:controller => 'timelog', :action => 'details', :project_id => entry.project}},
|
|
| 30 | 35 |
:author => :user, |
| 31 | 36 |
:description => :comments |
| 32 | 37 |
|
| 33 |
validates_presence_of :user_id, :activity_id, :project_id, :hours, :spent_on |
|
| 38 |
validates_presence_of :user_id, :activity_id, :project_id, :spent_on |
|
| 34 | 39 |
validates_numericality_of :hours, :allow_nil => true |
| 35 | 40 |
validates_length_of :comments, :maximum => 255, :allow_nil => true |
| 36 | 41 |
|
| ... | ... | |
| 48 | 53 |
|
| 49 | 54 |
def validate |
| 50 | 55 |
errors.add :hours, :activerecord_error_invalid if hours && (hours < 0 || hours >= 1000) |
| 56 |
|
|
| 57 |
if !start_time && !hours |
|
| 58 |
#rather verbose, but l() always translate to English here for some reason |
|
| 59 |
errors.add :hours, ll(User.current.language, |
|
| 60 |
:activerecord_error_field_must_be_set_if_other_is_not, |
|
| 61 |
ll(User.current.language, :field_start_time)) |
|
| 62 |
|
|
| 63 |
errors.add :start_time, ll(User.current.language, |
|
| 64 |
:activerecord_error_field_must_be_set_if_other_is_not, |
|
| 65 |
ll(User.current.language, :field_hours)) |
|
| 66 |
end |
|
| 67 |
|
|
| 51 | 68 |
errors.add :project_id, :activerecord_error_invalid if project.nil? |
| 52 | 69 |
errors.add :issue_id, :activerecord_error_invalid if (issue_id && !issue) || (issue && project!=issue.project) |
| 53 | 70 |
end |
| ... | ... | |
| 75 | 92 |
yield |
| 76 | 93 |
end |
| 77 | 94 |
end |
| 95 |
|
|
| 96 |
def before_save |
|
| 97 |
if !hours && start_time && end_time |
|
| 98 |
self.hours = (end_time - start_time) / 3600 |
|
| 99 |
end |
|
| 100 |
end |
|
| 101 |
|
|
| 102 |
def find_intersecting_entries |
|
| 103 |
params = {:start_time => start_time, :end_time => end_time, :id => id}
|
|
| 104 |
|
|
| 105 |
self.class.find_all_by_user_id(user_id, :conditions => |
|
| 106 |
["(" +
|
|
| 107 |
#this entry's start time or end time is between other's start_time and end_time |
|
| 108 |
"start_time < :start_time and :start_time < end_time OR " + |
|
| 109 |
"start_time < :end_time and :end_time < end_time OR " + |
|
| 110 |
#other's entry's start time or end time is between this entry's start_time and end_time |
|
| 111 |
"start_time > :start_time and start_time < :end_time OR " + |
|
| 112 |
"end_time > :start_time and end_time < :end_time" + |
|
| 113 |
")" + |
|
| 114 |
"and id <> :id", params]) |
|
| 115 |
end |
|
| 78 | 116 |
end |
| lang/bg.yml (working copy) | ||
|---|---|---|
| 632 | 632 |
setting_mail_handler_api_enabled: Enable WS for incoming emails |
| 633 | 633 |
setting_mail_handler_api_key: API key |
| 634 | 634 |
text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." |
| 635 |
field_start_time: Start Time |
|
| 636 |
field_end_time: End Time |
|
| 637 |
text_in_progress: in progress |
|
| 638 |
activerecord_error_field_must_be_set_if_other_is_not: must be set if %s is not |
|
| 639 |
text_clear_to_recalculate_time_by_range: Clear to recalculate by start/end time |
|
| 640 |
text_and: and |
|
| 641 |
text_time_entry_intersecting_notice: Notice that this timelog entry (%s) intersects with %s. |
|
| 642 |
text_time_entry_intersecting_notice_entry: entry |
|
| 643 |
text_time_entry_intersecting_notice_entry_plural: entries |
|
| 644 |
button_now: Now |
|
| lang/cs.yml (working copy) | ||
|---|---|---|
| 637 | 637 |
setting_mail_handler_api_enabled: Enable WS for incoming emails |
| 638 | 638 |
setting_mail_handler_api_key: API key |
| 639 | 639 |
text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." |
| 640 |
field_start_time: Start Time |
|
| 641 |
field_end_time: End Time |
|
| 642 |
text_in_progress: in progress |
|
| 643 |
activerecord_error_field_must_be_set_if_other_is_not: must be set if %s is not |
|
| 644 |
text_clear_to_recalculate_time_by_range: Clear to recalculate by start/end time |
|
| 645 |
text_and: and |
|
| 646 |
text_time_entry_intersecting_notice: Notice that this timelog entry (%s) intersects with %s. |
|
| 647 |
text_time_entry_intersecting_notice_entry: entry |
|
| 648 |
text_time_entry_intersecting_notice_entry_plural: entries |
|
| 649 |
button_now: Now |
|
| lang/da.yml (working copy) | ||
|---|---|---|
| 634 | 634 |
setting_mail_handler_api_enabled: Enable WS for incoming emails |
| 635 | 635 |
setting_mail_handler_api_key: API key |
| 636 | 636 |
text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." |
| 637 |
field_start_time: Start Time |
|
| 638 |
field_end_time: End Time |
|
| 639 |
text_in_progress: in progress |
|
| 640 |
activerecord_error_field_must_be_set_if_other_is_not: must be set if %s is not |
|
| 641 |
text_clear_to_recalculate_time_by_range: Clear to recalculate by start/end time |
|
| 642 |
text_and: and |
|
| 643 |
text_time_entry_intersecting_notice: Notice that this timelog entry (%s) intersects with %s. |
|
| 644 |
text_time_entry_intersecting_notice_entry: entry |
|
| 645 |
text_time_entry_intersecting_notice_entry_plural: entries |
|
| 646 |
button_now: Now |
|
| lang/de.yml (working copy) | ||
|---|---|---|
| 633 | 633 |
setting_mail_handler_api_enabled: Enable WS for incoming emails |
| 634 | 634 |
setting_mail_handler_api_key: API key |
| 635 | 635 |
text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." |
| 636 |
field_start_time: Start Time |
|
| 637 |
field_end_time: End Time |
|
| 638 |
text_in_progress: in progress |
|
| 639 |
activerecord_error_field_must_be_set_if_other_is_not: must be set if %s is not |
|
| 640 |
text_clear_to_recalculate_time_by_range: Clear to recalculate by start/end time |
|
| 641 |
text_and: and |
|
| 642 |
text_time_entry_intersecting_notice: Notice that this timelog entry (%s) intersects with %s. |
|
| 643 |
text_time_entry_intersecting_notice_entry: entry |
|
| 644 |
text_time_entry_intersecting_notice_entry_plural: entries |
|
| 645 |
button_now: Now |
|
| lang/en.yml (working copy) | ||
|---|---|---|
| 170 | 170 |
field_hours: Hours |
| 171 | 171 |
field_activity: Activity |
| 172 | 172 |
field_spent_on: Date |
| 173 |
field_start_time: Start Time |
|
| 174 |
field_end_time: End Time |
|
| 173 | 175 |
field_identifier: Identifier |
| 174 | 176 |
field_is_filter: Used as a filter |
| 175 | 177 |
field_issue_to_id: Related issue |
| ... | ... | |
| 558 | 560 |
button_annotate: Annotate |
| 559 | 561 |
button_update: Update |
| 560 | 562 |
button_configure: Configure |
| 563 |
button_now: Now |
|
| 561 | 564 |
|
| 562 | 565 |
status_active: active |
| 563 | 566 |
status_registered: registered |
| ... | ... | |
| 633 | 636 |
enumeration_issue_priorities: Issue priorities |
| 634 | 637 |
enumeration_doc_categories: Document categories |
| 635 | 638 |
enumeration_activities: Activities (time tracking) |
| 639 |
text_in_progress: in progress |
|
| 640 |
activerecord_error_field_must_be_set_if_other_is_not: must be set if %s is not |
|
| 641 |
text_clear_to_recalculate_time_by_range: Clear to recalculate by start/end time |
|
| 642 |
text_and: and |
|
| 643 |
text_time_entry_intersecting_notice: Notice that this timelog entry (%s) intersects with %s. |
|
| 644 |
text_time_entry_intersecting_notice_entry: entry |
|
| 645 |
text_time_entry_intersecting_notice_entry_plural: entries |
|
| lang/es.yml (working copy) | ||
|---|---|---|
| 635 | 635 |
setting_mail_handler_api_enabled: Enable WS for incoming emails |
| 636 | 636 |
setting_mail_handler_api_key: API key |
| 637 | 637 |
text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." |
| 638 |
field_start_time: Start Time |
|
| 639 |
field_end_time: End Time |
|
| 640 |
text_in_progress: in progress |
|
| 641 |
activerecord_error_field_must_be_set_if_other_is_not: must be set if %s is not |
|
| 642 |
text_clear_to_recalculate_time_by_range: Clear to recalculate by start/end time |
|
| 643 |
text_and: and |
|
| 644 |
text_time_entry_intersecting_notice: Notice that this timelog entry (%s) intersects with %s. |
|
| 645 |
text_time_entry_intersecting_notice_entry: entry |
|
| 646 |
text_time_entry_intersecting_notice_entry_plural: entries |
|
| 647 |
button_now: Now |
|
| lang/fi.yml (working copy) | ||
|---|---|---|
| 632 | 632 |
setting_mail_handler_api_enabled: Enable WS for incoming emails |
| 633 | 633 |
setting_mail_handler_api_key: API key |
| 634 | 634 |
text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." |
| 635 |
field_start_time: Start Time |
|
| 636 |
field_end_time: End Time |
|
| 637 |
text_in_progress: in progress |
|
| 638 |
activerecord_error_field_must_be_set_if_other_is_not: must be set if %s is not |
|
| 639 |
text_clear_to_recalculate_time_by_range: Clear to recalculate by start/end time |
|
| 640 |
text_and: and |
|
| 641 |
text_time_entry_intersecting_notice: Notice that this timelog entry (%s) intersects with %s. |
|
| 642 |
text_time_entry_intersecting_notice_entry: entry |
|
| 643 |
text_time_entry_intersecting_notice_entry_plural: entries |
|
| 644 |
button_now: Now |
|
| lang/fr.yml (working copy) | ||
|---|---|---|
| 633 | 633 |
enumeration_issue_priorities: Priorités des demandes |
| 634 | 634 |
enumeration_doc_categories: Catégories des documents |
| 635 | 635 |
enumeration_activities: Activités (suivi du temps) |
| 636 |
field_start_time: Start Time |
|
| 637 |
field_end_time: End Time |
|
| 638 |
text_in_progress: in progress |
|
| 639 |
activerecord_error_field_must_be_set_if_other_is_not: must be set if %s is not |
|
| 640 |
text_clear_to_recalculate_time_by_range: Clear to recalculate by start/end time |
|
| 641 |
text_and: and |
|
| 642 |
text_time_entry_intersecting_notice: Notice that this timelog entry (%s) intersects with %s. |
|
| 643 |
text_time_entry_intersecting_notice_entry: entry |
|
| 644 |
text_time_entry_intersecting_notice_entry_plural: entries |
|
| 645 |
button_now: Now |
|
| lang/he.yml (working copy) | ||
|---|---|---|
| 632 | 632 |
setting_mail_handler_api_enabled: Enable WS for incoming emails |
| 633 | 633 |
setting_mail_handler_api_key: API key |
| 634 | 634 |
text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." |
| 635 |
field_start_time: Start Time |
|
| 636 |
field_end_time: End Time |
|
| 637 |
text_in_progress: in progress |
|
| 638 |
activerecord_error_field_must_be_set_if_other_is_not: must be set if %s is not |
|
| 639 |
text_clear_to_recalculate_time_by_range: Clear to recalculate by start/end time |
|
| 640 |
text_and: and |
|
| 641 |
text_time_entry_intersecting_notice: Notice that this timelog entry (%s) intersects with %s. |
|
| 642 |
text_time_entry_intersecting_notice_entry: entry |
|
| 643 |
text_time_entry_intersecting_notice_entry_plural: entries |
|
| 644 |
button_now: Now |
|
| lang/hu.yml (working copy) | ||
|---|---|---|
| 633 | 633 |
setting_mail_handler_api_enabled: Web Service engedélyezése a beérkezett levelekhez |
| 634 | 634 |
setting_mail_handler_api_key: API kulcs |
| 635 | 635 |
text_email_delivery_not_configured: "Az E-mail küldés nincs konfigurálva, és az értesítések ki vannak kapcsolva.\nÁllítsd be az SMTP szervert a config/email.yml fájlban és indítsd újra az alkalmazást, hogy érvénybe lépjen." |
| 636 |
field_start_time: Start Time |
|
| 637 |
field_end_time: End Time |
|
| 638 |
text_in_progress: in progress |
|
| 639 |
activerecord_error_field_must_be_set_if_other_is_not: must be set if %s is not |
|
| 640 |
text_clear_to_recalculate_time_by_range: Clear to recalculate by start/end time |
|
| 641 |
text_and: and |
|
| 642 |
text_time_entry_intersecting_notice: Notice that this timelog entry (%s) intersects with %s. |
|
| 643 |
text_time_entry_intersecting_notice_entry: entry |
|
| 644 |
text_time_entry_intersecting_notice_entry_plural: entries |
|
| 645 |
button_now: Now |
|
| lang/it.yml (working copy) | ||
|---|---|---|
| 632 | 632 |
setting_mail_handler_api_enabled: Abilita WS per le e-mail in arrivo |
| 633 | 633 |
setting_mail_handler_api_key: chiave API |
| 634 | 634 |
text_email_delivery_not_configured: "La consegna via e-mail non è configurata e le notifiche sono disabilitate.\nConfigura il tuo server SMTP in config/email.yml e riavvia l'applicazione per abilitarle." |
| 635 |
field_start_time: Start Time |
|
| 636 |
field_end_time: End Time |
|
| 637 |
text_in_progress: in progress |
|
| 638 |
activerecord_error_field_must_be_set_if_other_is_not: must be set if %s is not |
|
| 639 |
text_clear_to_recalculate_time_by_range: Clear to recalculate by start/end time |
|
| 640 |
text_and: and |
|
| 641 |
text_time_entry_intersecting_notice: Notice that this timelog entry (%s) intersects with %s. |
|
| 642 |
text_time_entry_intersecting_notice_entry: entry |
|
| 643 |
text_time_entry_intersecting_notice_entry_plural: entries |
|
| 644 |
button_now: Now |
|
| lang/ja.yml (working copy) | ||
|---|---|---|
| 633 | 633 |
setting_mail_handler_api_enabled: Enable WS for incoming emails |
| 634 | 634 |
setting_mail_handler_api_key: API key |
| 635 | 635 |
text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." |
| 636 |
field_start_time: Start Time |
|
| 637 |
field_end_time: End Time |
|
| 638 |
text_in_progress: in progress |
|
| 639 |
activerecord_error_field_must_be_set_if_other_is_not: must be set if %s is not |
|
| 640 |
text_clear_to_recalculate_time_by_range: Clear to recalculate by start/end time |
|
| 641 |
text_and: and |
|
| 642 |
text_time_entry_intersecting_notice: Notice that this timelog entry (%s) intersects with %s. |
|
| 643 |
text_time_entry_intersecting_notice_entry: entry |
|
| 644 |
text_time_entry_intersecting_notice_entry_plural: entries |
|
| 645 |
button_now: Now |
|
| lang/ko.yml (working copy) | ||
|---|---|---|
| 632 | 632 |
setting_mail_handler_api_enabled: Enable WS for incoming emails |
| 633 | 633 |
setting_mail_handler_api_key: API key |
| 634 | 634 |
text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." |
| 635 |
field_start_time: Start Time |
|
| 636 |
field_end_time: End Time |
|
| 637 |
text_in_progress: in progress |
|
| 638 |
activerecord_error_field_must_be_set_if_other_is_not: must be set if %s is not |
|
| 639 |
text_clear_to_recalculate_time_by_range: Clear to recalculate by start/end time |
|
| 640 |
text_and: and |
|
| 641 |
text_time_entry_intersecting_notice: Notice that this timelog entry (%s) intersects with %s. |
|
| 642 |
text_time_entry_intersecting_notice_entry: entry |
|
| 643 |
text_time_entry_intersecting_notice_entry_plural: entries |
|
| 644 |
button_now: Now |
|
| lang/lt.yml (working copy) | ||
|---|---|---|
| 635 | 635 |
setting_mail_handler_api_key: API raktas |
| 636 | 636 |
|
| 637 | 637 |
text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." |
| 638 |
field_start_time: Start Time |
|
| 639 |
field_end_time: End Time |
|
| 640 |
text_in_progress: in progress |
|
| 641 |
activerecord_error_field_must_be_set_if_other_is_not: must be set if %s is not |
|
| 642 |
text_clear_to_recalculate_time_by_range: Clear to recalculate by start/end time |
|
| 643 |
text_and: and |
|
| 644 |
text_time_entry_intersecting_notice: Notice that this timelog entry (%s) intersects with %s. |
|
| 645 |
text_time_entry_intersecting_notice_entry: entry |
|
| 646 |
text_time_entry_intersecting_notice_entry_plural: entries |
|
| 647 |
button_now: Now |
|
| lang/nl.yml (working copy) | ||
|---|---|---|
| 633 | 633 |
setting_mail_handler_api_enabled: Enable WS for incoming emails |
| 634 | 634 |
setting_mail_handler_api_key: API key |
| 635 | 635 |
text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." |
| 636 |
field_start_time: Start Time |
|
| 637 |
field_end_time: End Time |
|
| 638 |
text_in_progress: in progress |
|
| 639 |
activerecord_error_field_must_be_set_if_other_is_not: must be set if %s is not |
|
| 640 |
text_clear_to_recalculate_time_by_range: Clear to recalculate by start/end time |
|
| 641 |
text_and: and |
|
| 642 |
text_time_entry_intersecting_notice: Notice that this timelog entry (%s) intersects with %s. |
|
| 643 |
text_time_entry_intersecting_notice_entry: entry |
|
| 644 |
text_time_entry_intersecting_notice_entry_plural: entries |
|
| 645 |
button_now: Now |
|
| lang/no.yml (working copy) | ||
|---|---|---|
| 633 | 633 |
setting_mail_handler_api_enabled: Enable WS for incoming emails |
| 634 | 634 |
setting_mail_handler_api_key: API key |
| 635 | 635 |
text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." |
| 636 |
field_start_time: Start Time |
|
| 637 |
field_end_time: End Time |
|
| 638 |
text_in_progress: in progress |
|
| 639 |
activerecord_error_field_must_be_set_if_other_is_not: must be set if %s is not |
|
| 640 |
text_clear_to_recalculate_time_by_range: Clear to recalculate by start/end time |
|
| 641 |
text_and: and |
|
| 642 |
text_time_entry_intersecting_notice: Notice that this timelog entry (%s) intersects with %s. |
|
| 643 |
text_time_entry_intersecting_notice_entry: entry |
|
| 644 |
text_time_entry_intersecting_notice_entry_plural: entries |
|
| 645 |
button_now: Now |
|
| lang/pl.yml (working copy) | ||
|---|---|---|
| 632 | 632 |
setting_mail_handler_api_enabled: Enable WS for incoming emails |
| 633 | 633 |
setting_mail_handler_api_key: API key |
| 634 | 634 |
text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." |
| 635 |
field_start_time: Start Time |
|
| 636 |
field_end_time: End Time |
|
| 637 |
text_in_progress: in progress |
|
| 638 |
activerecord_error_field_must_be_set_if_other_is_not: must be set if %s is not |
|
| 639 |
text_clear_to_recalculate_time_by_range: Clear to recalculate by start/end time |
|
| 640 |
text_and: and |
|
| 641 |
text_time_entry_intersecting_notice: Notice that this timelog entry (%s) intersects with %s. |
|
| 642 |
text_time_entry_intersecting_notice_entry: entry |
|
| 643 |
text_time_entry_intersecting_notice_entry_plural: entries |
|
| 644 |
button_now: Now |
|
| lang/pt-br.yml (working copy) | ||
|---|---|---|
| 632 | 632 |
setting_mail_handler_api_enabled: Enable WS for incoming emails |
| 633 | 633 |
setting_mail_handler_api_key: API key |
| 634 | 634 |
text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." |
| 635 |
field_start_time: Start Time |
|
| 636 |
field_end_time: End Time |
|
| 637 |
text_in_progress: in progress |
|
| 638 |
activerecord_error_field_must_be_set_if_other_is_not: must be set if %s is not |
|
| 639 |
text_clear_to_recalculate_time_by_range: Clear to recalculate by start/end time |
|
| 640 |
text_and: and |
|
| 641 |
text_time_entry_intersecting_notice: Notice that this timelog entry (%s) intersects with %s. |
|
| 642 |
text_time_entry_intersecting_notice_entry: entry |
|
| 643 |
text_time_entry_intersecting_notice_entry_plural: entries |
|
| 644 |
button_now: Now |
|
| lang/pt.yml (working copy) | ||
|---|---|---|
| 632 | 632 |
setting_mail_handler_api_enabled: Enable WS for incoming emails |
| 633 | 633 |
setting_mail_handler_api_key: API key |
| 634 | 634 |
text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." |
| 635 |
field_start_time: Start Time |
|
| 636 |
field_end_time: End Time |
|
| 637 |
text_in_progress: in progress |
|
| 638 |
activerecord_error_field_must_be_set_if_other_is_not: must be set if %s is not |
|
| 639 |
text_clear_to_recalculate_time_by_range: Clear to recalculate by start/end time |
|
| 640 |
text_and: and |
|
| 641 |
text_time_entry_intersecting_notice: Notice that this timelog entry (%s) intersects with %s. |
|
| 642 |
text_time_entry_intersecting_notice_entry: entry |
|
| 643 |
text_time_entry_intersecting_notice_entry_plural: entries |
|
| 644 |
button_now: Now |
|
| lang/ro.yml (working copy) | ||
|---|---|---|
| 632 | 632 |
setting_mail_handler_api_enabled: Enable WS for incoming emails |
| 633 | 633 |
setting_mail_handler_api_key: API key |
| 634 | 634 |
text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." |
| 635 |
field_start_time: Start Time |
|
| 636 |
field_end_time: End Time |
|
| 637 |
text_in_progress: in progress |
|
| 638 |
activerecord_error_field_must_be_set_if_other_is_not: must be set if %s is not |
|
| 639 |
text_clear_to_recalculate_time_by_range: Clear to recalculate by start/end time |
|
| 640 |
text_and: and |
|
| 641 |
text_time_entry_intersecting_notice: Notice that this timelog entry (%s) intersects with %s. |
|
| 642 |
text_time_entry_intersecting_notice_entry: entry |
|
| 643 |
text_time_entry_intersecting_notice_entry_plural: entries |
|
| 644 |
button_now: Now |
|
| lang/ru.yml (working copy) | ||
|---|---|---|
| 164 | 164 |
field_url: URL |
| 165 | 165 |
field_start_page: Стартовая страница |
| 166 | 166 |
field_subproject: Подпроект |
| 167 |
field_hours: Час(а,ов) |
|
| 167 |
field_hours: Часов |
|
| 168 | 168 |
field_activity: Деятельность |
| 169 | 169 |
field_spent_on: Дата |
| 170 |
field_start_time: Время начала |
|
| 171 |
field_end_time: Время окончания |
|
| 170 | 172 |
field_identifier: Ун. идентификатор |
| 171 | 173 |
field_is_filter: Используется в качестве фильтра |
| 172 | 174 |
field_issue_to_id: Связанные задачи |
| ... | ... | |
| 395 | 397 |
label_issue_tracking: Ситуация по задачам |
| 396 | 398 |
label_spent_time: Затраченное время |
| 397 | 399 |
label_f_hour: %.2f час |
| 398 |
label_f_hour_plural: %.2f часов(а) |
|
| 400 |
label_f_hour_plural: %.2f часов |
|
| 399 | 401 |
label_time_tracking: Учет времени |
| 400 | 402 |
label_change_plural: Правки |
| 401 | 403 |
label_statistics: Статистика |
| ... | ... | |
| 508 | 510 |
button_copy: Копировать |
| 509 | 511 |
button_annotate: Авторство |
| 510 | 512 |
button_update: Обновить |
| 513 |
button_now: Сейчас |
|
| 511 | 514 |
|
| 512 | 515 |
status_active: Активен |
| 513 | 516 |
status_registered: Зарегистрирован |
| ... | ... | |
| 636 | 639 |
setting_mail_handler_api_enabled: Включить веб-сервис для входящих сообщений |
| 637 | 640 |
setting_mail_handler_api_key: API ключ |
| 638 | 641 |
text_email_delivery_not_configured: "Параметры работы с почтовым сервером не настроены и функция уведомления по email не активна.\nНастроить параметры для вашего SMTP сервера вы можете в файле config/email.yml. Для применения изменений перезапустите приложение." |
| 642 |
text_in_progress: в процессе |
|
| 643 |
activerecord_error_field_must_be_set_if_other_is_not: необходимо задать, если значение поля '%s' не задано |
|
| 644 |
text_clear_to_recalculate_time_by_range: Очистите, чтобы пересчитать по времени окончания |
|
| 645 |
text_and: и |
|
| 646 |
text_time_entry_intersecting_notice: Обратите внимание, что эта запись о потраченном времени (%s) пересекается с %s. |
|
| 647 |
text_time_entry_intersecting_notice_entry: записью |
|
| 648 |
text_time_entry_intersecting_notice_entry_plural: записями |
|
| lang/sr.yml (working copy) | ||
|---|---|---|
| 633 | 633 |
setting_mail_handler_api_enabled: Enable WS for incoming emails |
| 634 | 634 |
setting_mail_handler_api_key: API key |
| 635 | 635 |
text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them." |
| 636 | ||