timelogging.patch

the patch - Artem Vasiliev, 2008-07-15 18:35

Download (62.4 KB)

 
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