##// END OF EJS Templates
User preference for monospaced / variable-width font in textareas (#23653)....
Jean-Philippe Lang -
r15371:2342fe9a755f
parent child
Show More
@@ -1,1368 +1,1371
1 # encoding: utf-8
1 # encoding: utf-8
2 #
2 #
3 # Redmine - project management software
3 # Redmine - project management software
4 # Copyright (C) 2006-2016 Jean-Philippe Lang
4 # Copyright (C) 2006-2016 Jean-Philippe Lang
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
9 # of the License, or (at your option) any later version.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
19
20 require 'forwardable'
20 require 'forwardable'
21 require 'cgi'
21 require 'cgi'
22
22
23 module ApplicationHelper
23 module ApplicationHelper
24 include Redmine::WikiFormatting::Macros::Definitions
24 include Redmine::WikiFormatting::Macros::Definitions
25 include Redmine::I18n
25 include Redmine::I18n
26 include GravatarHelper::PublicMethods
26 include GravatarHelper::PublicMethods
27 include Redmine::Pagination::Helper
27 include Redmine::Pagination::Helper
28 include Redmine::SudoMode::Helper
28 include Redmine::SudoMode::Helper
29 include Redmine::Themes::Helper
29 include Redmine::Themes::Helper
30 include Redmine::Hook::Helper
30 include Redmine::Hook::Helper
31 include Redmine::Helpers::URL
31 include Redmine::Helpers::URL
32
32
33 extend Forwardable
33 extend Forwardable
34 def_delegators :wiki_helper, :wikitoolbar_for, :heads_for_wiki_formatter
34 def_delegators :wiki_helper, :wikitoolbar_for, :heads_for_wiki_formatter
35
35
36 # Return true if user is authorized for controller/action, otherwise false
36 # Return true if user is authorized for controller/action, otherwise false
37 def authorize_for(controller, action)
37 def authorize_for(controller, action)
38 User.current.allowed_to?({:controller => controller, :action => action}, @project)
38 User.current.allowed_to?({:controller => controller, :action => action}, @project)
39 end
39 end
40
40
41 # Display a link if user is authorized
41 # Display a link if user is authorized
42 #
42 #
43 # @param [String] name Anchor text (passed to link_to)
43 # @param [String] name Anchor text (passed to link_to)
44 # @param [Hash] options Hash params. This will checked by authorize_for to see if the user is authorized
44 # @param [Hash] options Hash params. This will checked by authorize_for to see if the user is authorized
45 # @param [optional, Hash] html_options Options passed to link_to
45 # @param [optional, Hash] html_options Options passed to link_to
46 # @param [optional, Hash] parameters_for_method_reference Extra parameters for link_to
46 # @param [optional, Hash] parameters_for_method_reference Extra parameters for link_to
47 def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference)
47 def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference)
48 link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller] || params[:controller], options[:action])
48 link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller] || params[:controller], options[:action])
49 end
49 end
50
50
51 # Displays a link to user's account page if active
51 # Displays a link to user's account page if active
52 def link_to_user(user, options={})
52 def link_to_user(user, options={})
53 if user.is_a?(User)
53 if user.is_a?(User)
54 name = h(user.name(options[:format]))
54 name = h(user.name(options[:format]))
55 if user.active? || (User.current.admin? && user.logged?)
55 if user.active? || (User.current.admin? && user.logged?)
56 link_to name, user_path(user), :class => user.css_classes
56 link_to name, user_path(user), :class => user.css_classes
57 else
57 else
58 name
58 name
59 end
59 end
60 else
60 else
61 h(user.to_s)
61 h(user.to_s)
62 end
62 end
63 end
63 end
64
64
65 # Displays a link to +issue+ with its subject.
65 # Displays a link to +issue+ with its subject.
66 # Examples:
66 # Examples:
67 #
67 #
68 # link_to_issue(issue) # => Defect #6: This is the subject
68 # link_to_issue(issue) # => Defect #6: This is the subject
69 # link_to_issue(issue, :truncate => 6) # => Defect #6: This i...
69 # link_to_issue(issue, :truncate => 6) # => Defect #6: This i...
70 # link_to_issue(issue, :subject => false) # => Defect #6
70 # link_to_issue(issue, :subject => false) # => Defect #6
71 # link_to_issue(issue, :project => true) # => Foo - Defect #6
71 # link_to_issue(issue, :project => true) # => Foo - Defect #6
72 # link_to_issue(issue, :subject => false, :tracker => false) # => #6
72 # link_to_issue(issue, :subject => false, :tracker => false) # => #6
73 #
73 #
74 def link_to_issue(issue, options={})
74 def link_to_issue(issue, options={})
75 title = nil
75 title = nil
76 subject = nil
76 subject = nil
77 text = options[:tracker] == false ? "##{issue.id}" : "#{issue.tracker} ##{issue.id}"
77 text = options[:tracker] == false ? "##{issue.id}" : "#{issue.tracker} ##{issue.id}"
78 if options[:subject] == false
78 if options[:subject] == false
79 title = issue.subject.truncate(60)
79 title = issue.subject.truncate(60)
80 else
80 else
81 subject = issue.subject
81 subject = issue.subject
82 if truncate_length = options[:truncate]
82 if truncate_length = options[:truncate]
83 subject = subject.truncate(truncate_length)
83 subject = subject.truncate(truncate_length)
84 end
84 end
85 end
85 end
86 only_path = options[:only_path].nil? ? true : options[:only_path]
86 only_path = options[:only_path].nil? ? true : options[:only_path]
87 s = link_to(text, issue_url(issue, :only_path => only_path),
87 s = link_to(text, issue_url(issue, :only_path => only_path),
88 :class => issue.css_classes, :title => title)
88 :class => issue.css_classes, :title => title)
89 s << h(": #{subject}") if subject
89 s << h(": #{subject}") if subject
90 s = h("#{issue.project} - ") + s if options[:project]
90 s = h("#{issue.project} - ") + s if options[:project]
91 s
91 s
92 end
92 end
93
93
94 # Generates a link to an attachment.
94 # Generates a link to an attachment.
95 # Options:
95 # Options:
96 # * :text - Link text (default to attachment filename)
96 # * :text - Link text (default to attachment filename)
97 # * :download - Force download (default: false)
97 # * :download - Force download (default: false)
98 def link_to_attachment(attachment, options={})
98 def link_to_attachment(attachment, options={})
99 text = options.delete(:text) || attachment.filename
99 text = options.delete(:text) || attachment.filename
100 route_method = options.delete(:download) ? :download_named_attachment_url : :named_attachment_url
100 route_method = options.delete(:download) ? :download_named_attachment_url : :named_attachment_url
101 html_options = options.slice!(:only_path)
101 html_options = options.slice!(:only_path)
102 options[:only_path] = true unless options.key?(:only_path)
102 options[:only_path] = true unless options.key?(:only_path)
103 url = send(route_method, attachment, attachment.filename, options)
103 url = send(route_method, attachment, attachment.filename, options)
104 link_to text, url, html_options
104 link_to text, url, html_options
105 end
105 end
106
106
107 # Generates a link to a SCM revision
107 # Generates a link to a SCM revision
108 # Options:
108 # Options:
109 # * :text - Link text (default to the formatted revision)
109 # * :text - Link text (default to the formatted revision)
110 def link_to_revision(revision, repository, options={})
110 def link_to_revision(revision, repository, options={})
111 if repository.is_a?(Project)
111 if repository.is_a?(Project)
112 repository = repository.repository
112 repository = repository.repository
113 end
113 end
114 text = options.delete(:text) || format_revision(revision)
114 text = options.delete(:text) || format_revision(revision)
115 rev = revision.respond_to?(:identifier) ? revision.identifier : revision
115 rev = revision.respond_to?(:identifier) ? revision.identifier : revision
116 link_to(
116 link_to(
117 h(text),
117 h(text),
118 {:controller => 'repositories', :action => 'revision', :id => repository.project, :repository_id => repository.identifier_param, :rev => rev},
118 {:controller => 'repositories', :action => 'revision', :id => repository.project, :repository_id => repository.identifier_param, :rev => rev},
119 :title => l(:label_revision_id, format_revision(revision)),
119 :title => l(:label_revision_id, format_revision(revision)),
120 :accesskey => options[:accesskey]
120 :accesskey => options[:accesskey]
121 )
121 )
122 end
122 end
123
123
124 # Generates a link to a message
124 # Generates a link to a message
125 def link_to_message(message, options={}, html_options = nil)
125 def link_to_message(message, options={}, html_options = nil)
126 link_to(
126 link_to(
127 message.subject.truncate(60),
127 message.subject.truncate(60),
128 board_message_url(message.board_id, message.parent_id || message.id, {
128 board_message_url(message.board_id, message.parent_id || message.id, {
129 :r => (message.parent_id && message.id),
129 :r => (message.parent_id && message.id),
130 :anchor => (message.parent_id ? "message-#{message.id}" : nil),
130 :anchor => (message.parent_id ? "message-#{message.id}" : nil),
131 :only_path => true
131 :only_path => true
132 }.merge(options)),
132 }.merge(options)),
133 html_options
133 html_options
134 )
134 )
135 end
135 end
136
136
137 # Generates a link to a project if active
137 # Generates a link to a project if active
138 # Examples:
138 # Examples:
139 #
139 #
140 # link_to_project(project) # => link to the specified project overview
140 # link_to_project(project) # => link to the specified project overview
141 # link_to_project(project, {:only_path => false}, :class => "project") # => 3rd arg adds html options
141 # link_to_project(project, {:only_path => false}, :class => "project") # => 3rd arg adds html options
142 # link_to_project(project, {}, :class => "project") # => html options with default url (project overview)
142 # link_to_project(project, {}, :class => "project") # => html options with default url (project overview)
143 #
143 #
144 def link_to_project(project, options={}, html_options = nil)
144 def link_to_project(project, options={}, html_options = nil)
145 if project.archived?
145 if project.archived?
146 h(project.name)
146 h(project.name)
147 else
147 else
148 link_to project.name,
148 link_to project.name,
149 project_url(project, {:only_path => true}.merge(options)),
149 project_url(project, {:only_path => true}.merge(options)),
150 html_options
150 html_options
151 end
151 end
152 end
152 end
153
153
154 # Generates a link to a project settings if active
154 # Generates a link to a project settings if active
155 def link_to_project_settings(project, options={}, html_options=nil)
155 def link_to_project_settings(project, options={}, html_options=nil)
156 if project.active?
156 if project.active?
157 link_to project.name, settings_project_path(project, options), html_options
157 link_to project.name, settings_project_path(project, options), html_options
158 elsif project.archived?
158 elsif project.archived?
159 h(project.name)
159 h(project.name)
160 else
160 else
161 link_to project.name, project_path(project, options), html_options
161 link_to project.name, project_path(project, options), html_options
162 end
162 end
163 end
163 end
164
164
165 # Generates a link to a version
165 # Generates a link to a version
166 def link_to_version(version, options = {})
166 def link_to_version(version, options = {})
167 return '' unless version && version.is_a?(Version)
167 return '' unless version && version.is_a?(Version)
168 options = {:title => format_date(version.effective_date)}.merge(options)
168 options = {:title => format_date(version.effective_date)}.merge(options)
169 link_to_if version.visible?, format_version_name(version), version_path(version), options
169 link_to_if version.visible?, format_version_name(version), version_path(version), options
170 end
170 end
171
171
172 # Helper that formats object for html or text rendering
172 # Helper that formats object for html or text rendering
173 def format_object(object, html=true, &block)
173 def format_object(object, html=true, &block)
174 if block_given?
174 if block_given?
175 object = yield object
175 object = yield object
176 end
176 end
177 case object.class.name
177 case object.class.name
178 when 'Array'
178 when 'Array'
179 object.map {|o| format_object(o, html)}.join(', ').html_safe
179 object.map {|o| format_object(o, html)}.join(', ').html_safe
180 when 'Time'
180 when 'Time'
181 format_time(object)
181 format_time(object)
182 when 'Date'
182 when 'Date'
183 format_date(object)
183 format_date(object)
184 when 'Fixnum'
184 when 'Fixnum'
185 object.to_s
185 object.to_s
186 when 'Float'
186 when 'Float'
187 sprintf "%.2f", object
187 sprintf "%.2f", object
188 when 'User'
188 when 'User'
189 html ? link_to_user(object) : object.to_s
189 html ? link_to_user(object) : object.to_s
190 when 'Project'
190 when 'Project'
191 html ? link_to_project(object) : object.to_s
191 html ? link_to_project(object) : object.to_s
192 when 'Version'
192 when 'Version'
193 html ? link_to_version(object) : object.to_s
193 html ? link_to_version(object) : object.to_s
194 when 'TrueClass'
194 when 'TrueClass'
195 l(:general_text_Yes)
195 l(:general_text_Yes)
196 when 'FalseClass'
196 when 'FalseClass'
197 l(:general_text_No)
197 l(:general_text_No)
198 when 'Issue'
198 when 'Issue'
199 object.visible? && html ? link_to_issue(object) : "##{object.id}"
199 object.visible? && html ? link_to_issue(object) : "##{object.id}"
200 when 'CustomValue', 'CustomFieldValue'
200 when 'CustomValue', 'CustomFieldValue'
201 if object.custom_field
201 if object.custom_field
202 f = object.custom_field.format.formatted_custom_value(self, object, html)
202 f = object.custom_field.format.formatted_custom_value(self, object, html)
203 if f.nil? || f.is_a?(String)
203 if f.nil? || f.is_a?(String)
204 f
204 f
205 else
205 else
206 format_object(f, html, &block)
206 format_object(f, html, &block)
207 end
207 end
208 else
208 else
209 object.value.to_s
209 object.value.to_s
210 end
210 end
211 else
211 else
212 html ? h(object) : object.to_s
212 html ? h(object) : object.to_s
213 end
213 end
214 end
214 end
215
215
216 def wiki_page_path(page, options={})
216 def wiki_page_path(page, options={})
217 url_for({:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title}.merge(options))
217 url_for({:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title}.merge(options))
218 end
218 end
219
219
220 def thumbnail_tag(attachment)
220 def thumbnail_tag(attachment)
221 link_to image_tag(thumbnail_path(attachment)),
221 link_to image_tag(thumbnail_path(attachment)),
222 named_attachment_path(attachment, attachment.filename),
222 named_attachment_path(attachment, attachment.filename),
223 :title => attachment.filename
223 :title => attachment.filename
224 end
224 end
225
225
226 def toggle_link(name, id, options={})
226 def toggle_link(name, id, options={})
227 onclick = "$('##{id}').toggle(); "
227 onclick = "$('##{id}').toggle(); "
228 onclick << (options[:focus] ? "$('##{options[:focus]}').focus(); " : "this.blur(); ")
228 onclick << (options[:focus] ? "$('##{options[:focus]}').focus(); " : "this.blur(); ")
229 onclick << "return false;"
229 onclick << "return false;"
230 link_to(name, "#", :onclick => onclick)
230 link_to(name, "#", :onclick => onclick)
231 end
231 end
232
232
233 def format_activity_title(text)
233 def format_activity_title(text)
234 h(truncate_single_line_raw(text, 100))
234 h(truncate_single_line_raw(text, 100))
235 end
235 end
236
236
237 def format_activity_day(date)
237 def format_activity_day(date)
238 date == User.current.today ? l(:label_today).titleize : format_date(date)
238 date == User.current.today ? l(:label_today).titleize : format_date(date)
239 end
239 end
240
240
241 def format_activity_description(text)
241 def format_activity_description(text)
242 h(text.to_s.truncate(120).gsub(%r{[\r\n]*<(pre|code)>.*$}m, '...')
242 h(text.to_s.truncate(120).gsub(%r{[\r\n]*<(pre|code)>.*$}m, '...')
243 ).gsub(/[\r\n]+/, "<br />").html_safe
243 ).gsub(/[\r\n]+/, "<br />").html_safe
244 end
244 end
245
245
246 def format_version_name(version)
246 def format_version_name(version)
247 if version.project == @project
247 if version.project == @project
248 h(version)
248 h(version)
249 else
249 else
250 h("#{version.project} - #{version}")
250 h("#{version.project} - #{version}")
251 end
251 end
252 end
252 end
253
253
254 def due_date_distance_in_words(date)
254 def due_date_distance_in_words(date)
255 if date
255 if date
256 l((date < User.current.today ? :label_roadmap_overdue : :label_roadmap_due_in), distance_of_date_in_words(User.current.today, date))
256 l((date < User.current.today ? :label_roadmap_overdue : :label_roadmap_due_in), distance_of_date_in_words(User.current.today, date))
257 end
257 end
258 end
258 end
259
259
260 # Renders a tree of projects as a nested set of unordered lists
260 # Renders a tree of projects as a nested set of unordered lists
261 # The given collection may be a subset of the whole project tree
261 # The given collection may be a subset of the whole project tree
262 # (eg. some intermediate nodes are private and can not be seen)
262 # (eg. some intermediate nodes are private and can not be seen)
263 def render_project_nested_lists(projects, &block)
263 def render_project_nested_lists(projects, &block)
264 s = ''
264 s = ''
265 if projects.any?
265 if projects.any?
266 ancestors = []
266 ancestors = []
267 original_project = @project
267 original_project = @project
268 projects.sort_by(&:lft).each do |project|
268 projects.sort_by(&:lft).each do |project|
269 # set the project environment to please macros.
269 # set the project environment to please macros.
270 @project = project
270 @project = project
271 if (ancestors.empty? || project.is_descendant_of?(ancestors.last))
271 if (ancestors.empty? || project.is_descendant_of?(ancestors.last))
272 s << "<ul class='projects #{ ancestors.empty? ? 'root' : nil}'>\n"
272 s << "<ul class='projects #{ ancestors.empty? ? 'root' : nil}'>\n"
273 else
273 else
274 ancestors.pop
274 ancestors.pop
275 s << "</li>"
275 s << "</li>"
276 while (ancestors.any? && !project.is_descendant_of?(ancestors.last))
276 while (ancestors.any? && !project.is_descendant_of?(ancestors.last))
277 ancestors.pop
277 ancestors.pop
278 s << "</ul></li>\n"
278 s << "</ul></li>\n"
279 end
279 end
280 end
280 end
281 classes = (ancestors.empty? ? 'root' : 'child')
281 classes = (ancestors.empty? ? 'root' : 'child')
282 s << "<li class='#{classes}'><div class='#{classes}'>"
282 s << "<li class='#{classes}'><div class='#{classes}'>"
283 s << h(block_given? ? capture(project, &block) : project.name)
283 s << h(block_given? ? capture(project, &block) : project.name)
284 s << "</div>\n"
284 s << "</div>\n"
285 ancestors << project
285 ancestors << project
286 end
286 end
287 s << ("</li></ul>\n" * ancestors.size)
287 s << ("</li></ul>\n" * ancestors.size)
288 @project = original_project
288 @project = original_project
289 end
289 end
290 s.html_safe
290 s.html_safe
291 end
291 end
292
292
293 def render_page_hierarchy(pages, node=nil, options={})
293 def render_page_hierarchy(pages, node=nil, options={})
294 content = ''
294 content = ''
295 if pages[node]
295 if pages[node]
296 content << "<ul class=\"pages-hierarchy\">\n"
296 content << "<ul class=\"pages-hierarchy\">\n"
297 pages[node].each do |page|
297 pages[node].each do |page|
298 content << "<li>"
298 content << "<li>"
299 content << link_to(h(page.pretty_title), {:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title, :version => nil},
299 content << link_to(h(page.pretty_title), {:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title, :version => nil},
300 :title => (options[:timestamp] && page.updated_on ? l(:label_updated_time, distance_of_time_in_words(Time.now, page.updated_on)) : nil))
300 :title => (options[:timestamp] && page.updated_on ? l(:label_updated_time, distance_of_time_in_words(Time.now, page.updated_on)) : nil))
301 content << "\n" + render_page_hierarchy(pages, page.id, options) if pages[page.id]
301 content << "\n" + render_page_hierarchy(pages, page.id, options) if pages[page.id]
302 content << "</li>\n"
302 content << "</li>\n"
303 end
303 end
304 content << "</ul>\n"
304 content << "</ul>\n"
305 end
305 end
306 content.html_safe
306 content.html_safe
307 end
307 end
308
308
309 # Renders flash messages
309 # Renders flash messages
310 def render_flash_messages
310 def render_flash_messages
311 s = ''
311 s = ''
312 flash.each do |k,v|
312 flash.each do |k,v|
313 s << content_tag('div', v.html_safe, :class => "flash #{k}", :id => "flash_#{k}")
313 s << content_tag('div', v.html_safe, :class => "flash #{k}", :id => "flash_#{k}")
314 end
314 end
315 s.html_safe
315 s.html_safe
316 end
316 end
317
317
318 # Renders tabs and their content
318 # Renders tabs and their content
319 def render_tabs(tabs, selected=params[:tab])
319 def render_tabs(tabs, selected=params[:tab])
320 if tabs.any?
320 if tabs.any?
321 unless tabs.detect {|tab| tab[:name] == selected}
321 unless tabs.detect {|tab| tab[:name] == selected}
322 selected = nil
322 selected = nil
323 end
323 end
324 selected ||= tabs.first[:name]
324 selected ||= tabs.first[:name]
325 render :partial => 'common/tabs', :locals => {:tabs => tabs, :selected_tab => selected}
325 render :partial => 'common/tabs', :locals => {:tabs => tabs, :selected_tab => selected}
326 else
326 else
327 content_tag 'p', l(:label_no_data), :class => "nodata"
327 content_tag 'p', l(:label_no_data), :class => "nodata"
328 end
328 end
329 end
329 end
330
330
331 # Renders the project quick-jump box
331 # Renders the project quick-jump box
332 def render_project_jump_box
332 def render_project_jump_box
333 return unless User.current.logged?
333 return unless User.current.logged?
334 projects = User.current.projects.active.select(:id, :name, :identifier, :lft, :rgt).to_a
334 projects = User.current.projects.active.select(:id, :name, :identifier, :lft, :rgt).to_a
335 if projects.any?
335 if projects.any?
336 options =
336 options =
337 ("<option value=''>#{ l(:label_jump_to_a_project) }</option>" +
337 ("<option value=''>#{ l(:label_jump_to_a_project) }</option>" +
338 '<option value="" disabled="disabled">---</option>').html_safe
338 '<option value="" disabled="disabled">---</option>').html_safe
339
339
340 options << project_tree_options_for_select(projects, :selected => @project) do |p|
340 options << project_tree_options_for_select(projects, :selected => @project) do |p|
341 { :value => project_path(:id => p, :jump => current_menu_item) }
341 { :value => project_path(:id => p, :jump => current_menu_item) }
342 end
342 end
343
343
344 content_tag( :span, nil, :class => 'jump-box-arrow') +
344 content_tag( :span, nil, :class => 'jump-box-arrow') +
345 select_tag('project_quick_jump_box', options, :onchange => 'if (this.value != \'\') { window.location = this.value; }')
345 select_tag('project_quick_jump_box', options, :onchange => 'if (this.value != \'\') { window.location = this.value; }')
346 end
346 end
347 end
347 end
348
348
349 def project_tree_options_for_select(projects, options = {})
349 def project_tree_options_for_select(projects, options = {})
350 s = ''.html_safe
350 s = ''.html_safe
351 if blank_text = options[:include_blank]
351 if blank_text = options[:include_blank]
352 if blank_text == true
352 if blank_text == true
353 blank_text = '&nbsp;'.html_safe
353 blank_text = '&nbsp;'.html_safe
354 end
354 end
355 s << content_tag('option', blank_text, :value => '')
355 s << content_tag('option', blank_text, :value => '')
356 end
356 end
357 project_tree(projects) do |project, level|
357 project_tree(projects) do |project, level|
358 name_prefix = (level > 0 ? '&nbsp;' * 2 * level + '&#187; ' : '').html_safe
358 name_prefix = (level > 0 ? '&nbsp;' * 2 * level + '&#187; ' : '').html_safe
359 tag_options = {:value => project.id}
359 tag_options = {:value => project.id}
360 if project == options[:selected] || (options[:selected].respond_to?(:include?) && options[:selected].include?(project))
360 if project == options[:selected] || (options[:selected].respond_to?(:include?) && options[:selected].include?(project))
361 tag_options[:selected] = 'selected'
361 tag_options[:selected] = 'selected'
362 else
362 else
363 tag_options[:selected] = nil
363 tag_options[:selected] = nil
364 end
364 end
365 tag_options.merge!(yield(project)) if block_given?
365 tag_options.merge!(yield(project)) if block_given?
366 s << content_tag('option', name_prefix + h(project), tag_options)
366 s << content_tag('option', name_prefix + h(project), tag_options)
367 end
367 end
368 s.html_safe
368 s.html_safe
369 end
369 end
370
370
371 # Yields the given block for each project with its level in the tree
371 # Yields the given block for each project with its level in the tree
372 #
372 #
373 # Wrapper for Project#project_tree
373 # Wrapper for Project#project_tree
374 def project_tree(projects, &block)
374 def project_tree(projects, &block)
375 Project.project_tree(projects, &block)
375 Project.project_tree(projects, &block)
376 end
376 end
377
377
378 def principals_check_box_tags(name, principals)
378 def principals_check_box_tags(name, principals)
379 s = ''
379 s = ''
380 principals.each do |principal|
380 principals.each do |principal|
381 s << "<label>#{ check_box_tag name, principal.id, false, :id => nil } #{h principal}</label>\n"
381 s << "<label>#{ check_box_tag name, principal.id, false, :id => nil } #{h principal}</label>\n"
382 end
382 end
383 s.html_safe
383 s.html_safe
384 end
384 end
385
385
386 # Returns a string for users/groups option tags
386 # Returns a string for users/groups option tags
387 def principals_options_for_select(collection, selected=nil)
387 def principals_options_for_select(collection, selected=nil)
388 s = ''
388 s = ''
389 if collection.include?(User.current)
389 if collection.include?(User.current)
390 s << content_tag('option', "<< #{l(:label_me)} >>", :value => User.current.id)
390 s << content_tag('option', "<< #{l(:label_me)} >>", :value => User.current.id)
391 end
391 end
392 groups = ''
392 groups = ''
393 collection.sort.each do |element|
393 collection.sort.each do |element|
394 selected_attribute = ' selected="selected"' if option_value_selected?(element, selected) || element.id.to_s == selected
394 selected_attribute = ' selected="selected"' if option_value_selected?(element, selected) || element.id.to_s == selected
395 (element.is_a?(Group) ? groups : s) << %(<option value="#{element.id}"#{selected_attribute}>#{h element.name}</option>)
395 (element.is_a?(Group) ? groups : s) << %(<option value="#{element.id}"#{selected_attribute}>#{h element.name}</option>)
396 end
396 end
397 unless groups.empty?
397 unless groups.empty?
398 s << %(<optgroup label="#{h(l(:label_group_plural))}">#{groups}</optgroup>)
398 s << %(<optgroup label="#{h(l(:label_group_plural))}">#{groups}</optgroup>)
399 end
399 end
400 s.html_safe
400 s.html_safe
401 end
401 end
402
402
403 def option_tag(name, text, value, selected=nil, options={})
403 def option_tag(name, text, value, selected=nil, options={})
404 content_tag 'option', value, options.merge(:value => value, :selected => (value == selected))
404 content_tag 'option', value, options.merge(:value => value, :selected => (value == selected))
405 end
405 end
406
406
407 def truncate_single_line_raw(string, length)
407 def truncate_single_line_raw(string, length)
408 string.to_s.truncate(length).gsub(%r{[\r\n]+}m, ' ')
408 string.to_s.truncate(length).gsub(%r{[\r\n]+}m, ' ')
409 end
409 end
410
410
411 # Truncates at line break after 250 characters or options[:length]
411 # Truncates at line break after 250 characters or options[:length]
412 def truncate_lines(string, options={})
412 def truncate_lines(string, options={})
413 length = options[:length] || 250
413 length = options[:length] || 250
414 if string.to_s =~ /\A(.{#{length}}.*?)$/m
414 if string.to_s =~ /\A(.{#{length}}.*?)$/m
415 "#{$1}..."
415 "#{$1}..."
416 else
416 else
417 string
417 string
418 end
418 end
419 end
419 end
420
420
421 def anchor(text)
421 def anchor(text)
422 text.to_s.gsub(' ', '_')
422 text.to_s.gsub(' ', '_')
423 end
423 end
424
424
425 def html_hours(text)
425 def html_hours(text)
426 text.gsub(%r{(\d+)\.(\d+)}, '<span class="hours hours-int">\1</span><span class="hours hours-dec">.\2</span>').html_safe
426 text.gsub(%r{(\d+)\.(\d+)}, '<span class="hours hours-int">\1</span><span class="hours hours-dec">.\2</span>').html_safe
427 end
427 end
428
428
429 def authoring(created, author, options={})
429 def authoring(created, author, options={})
430 l(options[:label] || :label_added_time_by, :author => link_to_user(author), :age => time_tag(created)).html_safe
430 l(options[:label] || :label_added_time_by, :author => link_to_user(author), :age => time_tag(created)).html_safe
431 end
431 end
432
432
433 def time_tag(time)
433 def time_tag(time)
434 text = distance_of_time_in_words(Time.now, time)
434 text = distance_of_time_in_words(Time.now, time)
435 if @project
435 if @project
436 link_to(text, project_activity_path(@project, :from => User.current.time_to_date(time)), :title => format_time(time))
436 link_to(text, project_activity_path(@project, :from => User.current.time_to_date(time)), :title => format_time(time))
437 else
437 else
438 content_tag('abbr', text, :title => format_time(time))
438 content_tag('abbr', text, :title => format_time(time))
439 end
439 end
440 end
440 end
441
441
442 def syntax_highlight_lines(name, content)
442 def syntax_highlight_lines(name, content)
443 lines = []
443 lines = []
444 syntax_highlight(name, content).each_line { |line| lines << line }
444 syntax_highlight(name, content).each_line { |line| lines << line }
445 lines
445 lines
446 end
446 end
447
447
448 def syntax_highlight(name, content)
448 def syntax_highlight(name, content)
449 Redmine::SyntaxHighlighting.highlight_by_filename(content, name)
449 Redmine::SyntaxHighlighting.highlight_by_filename(content, name)
450 end
450 end
451
451
452 def to_path_param(path)
452 def to_path_param(path)
453 str = path.to_s.split(%r{[/\\]}).select{|p| !p.blank?}.join("/")
453 str = path.to_s.split(%r{[/\\]}).select{|p| !p.blank?}.join("/")
454 str.blank? ? nil : str
454 str.blank? ? nil : str
455 end
455 end
456
456
457 def reorder_links(name, url, method = :post)
457 def reorder_links(name, url, method = :post)
458 # TODO: remove associated styles from application.css too
458 # TODO: remove associated styles from application.css too
459 ActiveSupport::Deprecation.warn "Application#reorder_links will be removed in Redmine 4."
459 ActiveSupport::Deprecation.warn "Application#reorder_links will be removed in Redmine 4."
460
460
461 link_to(l(:label_sort_highest),
461 link_to(l(:label_sort_highest),
462 url.merge({"#{name}[move_to]" => 'highest'}), :method => method,
462 url.merge({"#{name}[move_to]" => 'highest'}), :method => method,
463 :title => l(:label_sort_highest), :class => 'icon-only icon-move-top') +
463 :title => l(:label_sort_highest), :class => 'icon-only icon-move-top') +
464 link_to(l(:label_sort_higher),
464 link_to(l(:label_sort_higher),
465 url.merge({"#{name}[move_to]" => 'higher'}), :method => method,
465 url.merge({"#{name}[move_to]" => 'higher'}), :method => method,
466 :title => l(:label_sort_higher), :class => 'icon-only icon-move-up') +
466 :title => l(:label_sort_higher), :class => 'icon-only icon-move-up') +
467 link_to(l(:label_sort_lower),
467 link_to(l(:label_sort_lower),
468 url.merge({"#{name}[move_to]" => 'lower'}), :method => method,
468 url.merge({"#{name}[move_to]" => 'lower'}), :method => method,
469 :title => l(:label_sort_lower), :class => 'icon-only icon-move-down') +
469 :title => l(:label_sort_lower), :class => 'icon-only icon-move-down') +
470 link_to(l(:label_sort_lowest),
470 link_to(l(:label_sort_lowest),
471 url.merge({"#{name}[move_to]" => 'lowest'}), :method => method,
471 url.merge({"#{name}[move_to]" => 'lowest'}), :method => method,
472 :title => l(:label_sort_lowest), :class => 'icon-only icon-move-bottom')
472 :title => l(:label_sort_lowest), :class => 'icon-only icon-move-bottom')
473 end
473 end
474
474
475 def reorder_handle(object, options={})
475 def reorder_handle(object, options={})
476 data = {
476 data = {
477 :reorder_url => options[:url] || url_for(object),
477 :reorder_url => options[:url] || url_for(object),
478 :reorder_param => options[:param] || object.class.name.underscore
478 :reorder_param => options[:param] || object.class.name.underscore
479 }
479 }
480 content_tag('span', '',
480 content_tag('span', '',
481 :class => "sort-handle",
481 :class => "sort-handle",
482 :data => data,
482 :data => data,
483 :title => l(:button_sort))
483 :title => l(:button_sort))
484 end
484 end
485
485
486 def breadcrumb(*args)
486 def breadcrumb(*args)
487 elements = args.flatten
487 elements = args.flatten
488 elements.any? ? content_tag('p', (args.join(" \xc2\xbb ") + " \xc2\xbb ").html_safe, :class => 'breadcrumb') : nil
488 elements.any? ? content_tag('p', (args.join(" \xc2\xbb ") + " \xc2\xbb ").html_safe, :class => 'breadcrumb') : nil
489 end
489 end
490
490
491 def other_formats_links(&block)
491 def other_formats_links(&block)
492 concat('<p class="other-formats">'.html_safe + l(:label_export_to))
492 concat('<p class="other-formats">'.html_safe + l(:label_export_to))
493 yield Redmine::Views::OtherFormatsBuilder.new(self)
493 yield Redmine::Views::OtherFormatsBuilder.new(self)
494 concat('</p>'.html_safe)
494 concat('</p>'.html_safe)
495 end
495 end
496
496
497 def page_header_title
497 def page_header_title
498 if @project.nil? || @project.new_record?
498 if @project.nil? || @project.new_record?
499 h(Setting.app_title)
499 h(Setting.app_title)
500 else
500 else
501 b = []
501 b = []
502 ancestors = (@project.root? ? [] : @project.ancestors.visible.to_a)
502 ancestors = (@project.root? ? [] : @project.ancestors.visible.to_a)
503 if ancestors.any?
503 if ancestors.any?
504 root = ancestors.shift
504 root = ancestors.shift
505 b << link_to_project(root, {:jump => current_menu_item}, :class => 'root')
505 b << link_to_project(root, {:jump => current_menu_item}, :class => 'root')
506 if ancestors.size > 2
506 if ancestors.size > 2
507 b << "\xe2\x80\xa6"
507 b << "\xe2\x80\xa6"
508 ancestors = ancestors[-2, 2]
508 ancestors = ancestors[-2, 2]
509 end
509 end
510 b += ancestors.collect {|p| link_to_project(p, {:jump => current_menu_item}, :class => 'ancestor') }
510 b += ancestors.collect {|p| link_to_project(p, {:jump => current_menu_item}, :class => 'ancestor') }
511 end
511 end
512 b << content_tag(:span, h(@project), class: 'current-project')
512 b << content_tag(:span, h(@project), class: 'current-project')
513 if b.size > 1
513 if b.size > 1
514 separator = content_tag(:span, ' &raquo; '.html_safe, class: 'separator')
514 separator = content_tag(:span, ' &raquo; '.html_safe, class: 'separator')
515 path = safe_join(b[0..-2], separator) + separator
515 path = safe_join(b[0..-2], separator) + separator
516 b = [content_tag(:span, path.html_safe, class: 'breadcrumbs'), b[-1]]
516 b = [content_tag(:span, path.html_safe, class: 'breadcrumbs'), b[-1]]
517 end
517 end
518 safe_join b
518 safe_join b
519 end
519 end
520 end
520 end
521
521
522 # Returns a h2 tag and sets the html title with the given arguments
522 # Returns a h2 tag and sets the html title with the given arguments
523 def title(*args)
523 def title(*args)
524 strings = args.map do |arg|
524 strings = args.map do |arg|
525 if arg.is_a?(Array) && arg.size >= 2
525 if arg.is_a?(Array) && arg.size >= 2
526 link_to(*arg)
526 link_to(*arg)
527 else
527 else
528 h(arg.to_s)
528 h(arg.to_s)
529 end
529 end
530 end
530 end
531 html_title args.reverse.map {|s| (s.is_a?(Array) ? s.first : s).to_s}
531 html_title args.reverse.map {|s| (s.is_a?(Array) ? s.first : s).to_s}
532 content_tag('h2', strings.join(' &#187; ').html_safe)
532 content_tag('h2', strings.join(' &#187; ').html_safe)
533 end
533 end
534
534
535 # Sets the html title
535 # Sets the html title
536 # Returns the html title when called without arguments
536 # Returns the html title when called without arguments
537 # Current project name and app_title and automatically appended
537 # Current project name and app_title and automatically appended
538 # Exemples:
538 # Exemples:
539 # html_title 'Foo', 'Bar'
539 # html_title 'Foo', 'Bar'
540 # html_title # => 'Foo - Bar - My Project - Redmine'
540 # html_title # => 'Foo - Bar - My Project - Redmine'
541 def html_title(*args)
541 def html_title(*args)
542 if args.empty?
542 if args.empty?
543 title = @html_title || []
543 title = @html_title || []
544 title << @project.name if @project
544 title << @project.name if @project
545 title << Setting.app_title unless Setting.app_title == title.last
545 title << Setting.app_title unless Setting.app_title == title.last
546 title.reject(&:blank?).join(' - ')
546 title.reject(&:blank?).join(' - ')
547 else
547 else
548 @html_title ||= []
548 @html_title ||= []
549 @html_title += args
549 @html_title += args
550 end
550 end
551 end
551 end
552
552
553 # Returns the theme, controller name, and action as css classes for the
553 # Returns the theme, controller name, and action as css classes for the
554 # HTML body.
554 # HTML body.
555 def body_css_classes
555 def body_css_classes
556 css = []
556 css = []
557 if theme = Redmine::Themes.theme(Setting.ui_theme)
557 if theme = Redmine::Themes.theme(Setting.ui_theme)
558 css << 'theme-' + theme.name
558 css << 'theme-' + theme.name
559 end
559 end
560
560
561 css << 'project-' + @project.identifier if @project && @project.identifier.present?
561 css << 'project-' + @project.identifier if @project && @project.identifier.present?
562 css << 'controller-' + controller_name
562 css << 'controller-' + controller_name
563 css << 'action-' + action_name
563 css << 'action-' + action_name
564 if UserPreference::TEXTAREA_FONT_OPTIONS.include?(User.current.pref.textarea_font)
565 css << "textarea-#{User.current.pref.textarea_font}"
566 end
564 css.join(' ')
567 css.join(' ')
565 end
568 end
566
569
567 def accesskey(s)
570 def accesskey(s)
568 @used_accesskeys ||= []
571 @used_accesskeys ||= []
569 key = Redmine::AccessKeys.key_for(s)
572 key = Redmine::AccessKeys.key_for(s)
570 return nil if @used_accesskeys.include?(key)
573 return nil if @used_accesskeys.include?(key)
571 @used_accesskeys << key
574 @used_accesskeys << key
572 key
575 key
573 end
576 end
574
577
575 # Formats text according to system settings.
578 # Formats text according to system settings.
576 # 2 ways to call this method:
579 # 2 ways to call this method:
577 # * with a String: textilizable(text, options)
580 # * with a String: textilizable(text, options)
578 # * with an object and one of its attribute: textilizable(issue, :description, options)
581 # * with an object and one of its attribute: textilizable(issue, :description, options)
579 def textilizable(*args)
582 def textilizable(*args)
580 options = args.last.is_a?(Hash) ? args.pop : {}
583 options = args.last.is_a?(Hash) ? args.pop : {}
581 case args.size
584 case args.size
582 when 1
585 when 1
583 obj = options[:object]
586 obj = options[:object]
584 text = args.shift
587 text = args.shift
585 when 2
588 when 2
586 obj = args.shift
589 obj = args.shift
587 attr = args.shift
590 attr = args.shift
588 text = obj.send(attr).to_s
591 text = obj.send(attr).to_s
589 else
592 else
590 raise ArgumentError, 'invalid arguments to textilizable'
593 raise ArgumentError, 'invalid arguments to textilizable'
591 end
594 end
592 return '' if text.blank?
595 return '' if text.blank?
593 project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil)
596 project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil)
594 @only_path = only_path = options.delete(:only_path) == false ? false : true
597 @only_path = only_path = options.delete(:only_path) == false ? false : true
595
598
596 text = text.dup
599 text = text.dup
597 macros = catch_macros(text)
600 macros = catch_macros(text)
598 text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr)
601 text = Redmine::WikiFormatting.to_html(Setting.text_formatting, text, :object => obj, :attribute => attr)
599
602
600 @parsed_headings = []
603 @parsed_headings = []
601 @heading_anchors = {}
604 @heading_anchors = {}
602 @current_section = 0 if options[:edit_section_links]
605 @current_section = 0 if options[:edit_section_links]
603
606
604 parse_sections(text, project, obj, attr, only_path, options)
607 parse_sections(text, project, obj, attr, only_path, options)
605 text = parse_non_pre_blocks(text, obj, macros) do |text|
608 text = parse_non_pre_blocks(text, obj, macros) do |text|
606 [:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links].each do |method_name|
609 [:parse_inline_attachments, :parse_wiki_links, :parse_redmine_links].each do |method_name|
607 send method_name, text, project, obj, attr, only_path, options
610 send method_name, text, project, obj, attr, only_path, options
608 end
611 end
609 end
612 end
610 parse_headings(text, project, obj, attr, only_path, options)
613 parse_headings(text, project, obj, attr, only_path, options)
611
614
612 if @parsed_headings.any?
615 if @parsed_headings.any?
613 replace_toc(text, @parsed_headings)
616 replace_toc(text, @parsed_headings)
614 end
617 end
615
618
616 text.html_safe
619 text.html_safe
617 end
620 end
618
621
619 def parse_non_pre_blocks(text, obj, macros)
622 def parse_non_pre_blocks(text, obj, macros)
620 s = StringScanner.new(text)
623 s = StringScanner.new(text)
621 tags = []
624 tags = []
622 parsed = ''
625 parsed = ''
623 while !s.eos?
626 while !s.eos?
624 s.scan(/(.*?)(<(\/)?(pre|code)(.*?)>|\z)/im)
627 s.scan(/(.*?)(<(\/)?(pre|code)(.*?)>|\z)/im)
625 text, full_tag, closing, tag = s[1], s[2], s[3], s[4]
628 text, full_tag, closing, tag = s[1], s[2], s[3], s[4]
626 if tags.empty?
629 if tags.empty?
627 yield text
630 yield text
628 inject_macros(text, obj, macros) if macros.any?
631 inject_macros(text, obj, macros) if macros.any?
629 else
632 else
630 inject_macros(text, obj, macros, false) if macros.any?
633 inject_macros(text, obj, macros, false) if macros.any?
631 end
634 end
632 parsed << text
635 parsed << text
633 if tag
636 if tag
634 if closing
637 if closing
635 if tags.last && tags.last.casecmp(tag) == 0
638 if tags.last && tags.last.casecmp(tag) == 0
636 tags.pop
639 tags.pop
637 end
640 end
638 else
641 else
639 tags << tag.downcase
642 tags << tag.downcase
640 end
643 end
641 parsed << full_tag
644 parsed << full_tag
642 end
645 end
643 end
646 end
644 # Close any non closing tags
647 # Close any non closing tags
645 while tag = tags.pop
648 while tag = tags.pop
646 parsed << "</#{tag}>"
649 parsed << "</#{tag}>"
647 end
650 end
648 parsed
651 parsed
649 end
652 end
650
653
651 def parse_inline_attachments(text, project, obj, attr, only_path, options)
654 def parse_inline_attachments(text, project, obj, attr, only_path, options)
652 return if options[:inline_attachments] == false
655 return if options[:inline_attachments] == false
653
656
654 # when using an image link, try to use an attachment, if possible
657 # when using an image link, try to use an attachment, if possible
655 attachments = options[:attachments] || []
658 attachments = options[:attachments] || []
656 attachments += obj.attachments if obj.respond_to?(:attachments)
659 attachments += obj.attachments if obj.respond_to?(:attachments)
657 if attachments.present?
660 if attachments.present?
658 text.gsub!(/src="([^\/"]+\.(bmp|gif|jpg|jpe|jpeg|png))"(\s+alt="([^"]*)")?/i) do |m|
661 text.gsub!(/src="([^\/"]+\.(bmp|gif|jpg|jpe|jpeg|png))"(\s+alt="([^"]*)")?/i) do |m|
659 filename, ext, alt, alttext = $1.downcase, $2, $3, $4
662 filename, ext, alt, alttext = $1.downcase, $2, $3, $4
660 # search for the picture in attachments
663 # search for the picture in attachments
661 if found = Attachment.latest_attach(attachments, CGI.unescape(filename))
664 if found = Attachment.latest_attach(attachments, CGI.unescape(filename))
662 image_url = download_named_attachment_url(found, found.filename, :only_path => only_path)
665 image_url = download_named_attachment_url(found, found.filename, :only_path => only_path)
663 desc = found.description.to_s.gsub('"', '')
666 desc = found.description.to_s.gsub('"', '')
664 if !desc.blank? && alttext.blank?
667 if !desc.blank? && alttext.blank?
665 alt = " title=\"#{desc}\" alt=\"#{desc}\""
668 alt = " title=\"#{desc}\" alt=\"#{desc}\""
666 end
669 end
667 "src=\"#{image_url}\"#{alt}"
670 "src=\"#{image_url}\"#{alt}"
668 else
671 else
669 m
672 m
670 end
673 end
671 end
674 end
672 end
675 end
673 end
676 end
674
677
675 # Wiki links
678 # Wiki links
676 #
679 #
677 # Examples:
680 # Examples:
678 # [[mypage]]
681 # [[mypage]]
679 # [[mypage|mytext]]
682 # [[mypage|mytext]]
680 # wiki links can refer other project wikis, using project name or identifier:
683 # wiki links can refer other project wikis, using project name or identifier:
681 # [[project:]] -> wiki starting page
684 # [[project:]] -> wiki starting page
682 # [[project:|mytext]]
685 # [[project:|mytext]]
683 # [[project:mypage]]
686 # [[project:mypage]]
684 # [[project:mypage|mytext]]
687 # [[project:mypage|mytext]]
685 def parse_wiki_links(text, project, obj, attr, only_path, options)
688 def parse_wiki_links(text, project, obj, attr, only_path, options)
686 text.gsub!(/(!)?(\[\[([^\]\n\|]+)(\|([^\]\n\|]+))?\]\])/) do |m|
689 text.gsub!(/(!)?(\[\[([^\]\n\|]+)(\|([^\]\n\|]+))?\]\])/) do |m|
687 link_project = project
690 link_project = project
688 esc, all, page, title = $1, $2, $3, $5
691 esc, all, page, title = $1, $2, $3, $5
689 if esc.nil?
692 if esc.nil?
690 if page =~ /^([^\:]+)\:(.*)$/
693 if page =~ /^([^\:]+)\:(.*)$/
691 identifier, page = $1, $2
694 identifier, page = $1, $2
692 link_project = Project.find_by_identifier(identifier) || Project.find_by_name(identifier)
695 link_project = Project.find_by_identifier(identifier) || Project.find_by_name(identifier)
693 title ||= identifier if page.blank?
696 title ||= identifier if page.blank?
694 end
697 end
695
698
696 if link_project && link_project.wiki
699 if link_project && link_project.wiki
697 # extract anchor
700 # extract anchor
698 anchor = nil
701 anchor = nil
699 if page =~ /^(.+?)\#(.+)$/
702 if page =~ /^(.+?)\#(.+)$/
700 page, anchor = $1, $2
703 page, anchor = $1, $2
701 end
704 end
702 anchor = sanitize_anchor_name(anchor) if anchor.present?
705 anchor = sanitize_anchor_name(anchor) if anchor.present?
703 # check if page exists
706 # check if page exists
704 wiki_page = link_project.wiki.find_page(page)
707 wiki_page = link_project.wiki.find_page(page)
705 url = if anchor.present? && wiki_page.present? && (obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version)) && obj.page == wiki_page
708 url = if anchor.present? && wiki_page.present? && (obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version)) && obj.page == wiki_page
706 "##{anchor}"
709 "##{anchor}"
707 else
710 else
708 case options[:wiki_links]
711 case options[:wiki_links]
709 when :local; "#{page.present? ? Wiki.titleize(page) : ''}.html" + (anchor.present? ? "##{anchor}" : '')
712 when :local; "#{page.present? ? Wiki.titleize(page) : ''}.html" + (anchor.present? ? "##{anchor}" : '')
710 when :anchor; "##{page.present? ? Wiki.titleize(page) : title}" + (anchor.present? ? "_#{anchor}" : '') # used for single-file wiki export
713 when :anchor; "##{page.present? ? Wiki.titleize(page) : title}" + (anchor.present? ? "_#{anchor}" : '') # used for single-file wiki export
711 else
714 else
712 wiki_page_id = page.present? ? Wiki.titleize(page) : nil
715 wiki_page_id = page.present? ? Wiki.titleize(page) : nil
713 parent = wiki_page.nil? && obj.is_a?(WikiContent) && obj.page && project == link_project ? obj.page.title : nil
716 parent = wiki_page.nil? && obj.is_a?(WikiContent) && obj.page && project == link_project ? obj.page.title : nil
714 url_for(:only_path => only_path, :controller => 'wiki', :action => 'show', :project_id => link_project,
717 url_for(:only_path => only_path, :controller => 'wiki', :action => 'show', :project_id => link_project,
715 :id => wiki_page_id, :version => nil, :anchor => anchor, :parent => parent)
718 :id => wiki_page_id, :version => nil, :anchor => anchor, :parent => parent)
716 end
719 end
717 end
720 end
718 link_to(title.present? ? title.html_safe : h(page), url, :class => ('wiki-page' + (wiki_page ? '' : ' new')))
721 link_to(title.present? ? title.html_safe : h(page), url, :class => ('wiki-page' + (wiki_page ? '' : ' new')))
719 else
722 else
720 # project or wiki doesn't exist
723 # project or wiki doesn't exist
721 all
724 all
722 end
725 end
723 else
726 else
724 all
727 all
725 end
728 end
726 end
729 end
727 end
730 end
728
731
729 # Redmine links
732 # Redmine links
730 #
733 #
731 # Examples:
734 # Examples:
732 # Issues:
735 # Issues:
733 # #52 -> Link to issue #52
736 # #52 -> Link to issue #52
734 # Changesets:
737 # Changesets:
735 # r52 -> Link to revision 52
738 # r52 -> Link to revision 52
736 # commit:a85130f -> Link to scmid starting with a85130f
739 # commit:a85130f -> Link to scmid starting with a85130f
737 # Documents:
740 # Documents:
738 # document#17 -> Link to document with id 17
741 # document#17 -> Link to document with id 17
739 # document:Greetings -> Link to the document with title "Greetings"
742 # document:Greetings -> Link to the document with title "Greetings"
740 # document:"Some document" -> Link to the document with title "Some document"
743 # document:"Some document" -> Link to the document with title "Some document"
741 # Versions:
744 # Versions:
742 # version#3 -> Link to version with id 3
745 # version#3 -> Link to version with id 3
743 # version:1.0.0 -> Link to version named "1.0.0"
746 # version:1.0.0 -> Link to version named "1.0.0"
744 # version:"1.0 beta 2" -> Link to version named "1.0 beta 2"
747 # version:"1.0 beta 2" -> Link to version named "1.0 beta 2"
745 # Attachments:
748 # Attachments:
746 # attachment:file.zip -> Link to the attachment of the current object named file.zip
749 # attachment:file.zip -> Link to the attachment of the current object named file.zip
747 # Source files:
750 # Source files:
748 # source:some/file -> Link to the file located at /some/file in the project's repository
751 # source:some/file -> Link to the file located at /some/file in the project's repository
749 # source:some/file@52 -> Link to the file's revision 52
752 # source:some/file@52 -> Link to the file's revision 52
750 # source:some/file#L120 -> Link to line 120 of the file
753 # source:some/file#L120 -> Link to line 120 of the file
751 # source:some/file@52#L120 -> Link to line 120 of the file's revision 52
754 # source:some/file@52#L120 -> Link to line 120 of the file's revision 52
752 # export:some/file -> Force the download of the file
755 # export:some/file -> Force the download of the file
753 # Forum messages:
756 # Forum messages:
754 # message#1218 -> Link to message with id 1218
757 # message#1218 -> Link to message with id 1218
755 # Projects:
758 # Projects:
756 # project:someproject -> Link to project named "someproject"
759 # project:someproject -> Link to project named "someproject"
757 # project#3 -> Link to project with id 3
760 # project#3 -> Link to project with id 3
758 #
761 #
759 # Links can refer other objects from other projects, using project identifier:
762 # Links can refer other objects from other projects, using project identifier:
760 # identifier:r52
763 # identifier:r52
761 # identifier:document:"Some document"
764 # identifier:document:"Some document"
762 # identifier:version:1.0.0
765 # identifier:version:1.0.0
763 # identifier:source:some/file
766 # identifier:source:some/file
764 def parse_redmine_links(text, default_project, obj, attr, only_path, options)
767 def parse_redmine_links(text, default_project, obj, attr, only_path, options)
765 text.gsub!(%r{<a( [^>]+?)?>(.*?)</a>|([\s\(,\-\[\>]|^)(!)?(([a-z0-9\-_]+):)?(attachment|document|version|forum|news|message|project|commit|source|export)?(((#)|((([a-z0-9\-_]+)\|)?(r)))((\d+)((#note)?-(\d+))?)|(:)([^"\s<>][^\s<>]*?|"[^"]+?"))(?=(?=[[:punct:]][^A-Za-z0-9_/])|,|\s|\]|<|$)}) do |m|
768 text.gsub!(%r{<a( [^>]+?)?>(.*?)</a>|([\s\(,\-\[\>]|^)(!)?(([a-z0-9\-_]+):)?(attachment|document|version|forum|news|message|project|commit|source|export)?(((#)|((([a-z0-9\-_]+)\|)?(r)))((\d+)((#note)?-(\d+))?)|(:)([^"\s<>][^\s<>]*?|"[^"]+?"))(?=(?=[[:punct:]][^A-Za-z0-9_/])|,|\s|\]|<|$)}) do |m|
766 tag_content, leading, esc, project_prefix, project_identifier, prefix, repo_prefix, repo_identifier, sep, identifier, comment_suffix, comment_id = $2, $3, $4, $5, $6, $7, $12, $13, $10 || $14 || $20, $16 || $21, $17, $19
769 tag_content, leading, esc, project_prefix, project_identifier, prefix, repo_prefix, repo_identifier, sep, identifier, comment_suffix, comment_id = $2, $3, $4, $5, $6, $7, $12, $13, $10 || $14 || $20, $16 || $21, $17, $19
767 if tag_content
770 if tag_content
768 $&
771 $&
769 else
772 else
770 link = nil
773 link = nil
771 project = default_project
774 project = default_project
772 if project_identifier
775 if project_identifier
773 project = Project.visible.find_by_identifier(project_identifier)
776 project = Project.visible.find_by_identifier(project_identifier)
774 end
777 end
775 if esc.nil?
778 if esc.nil?
776 if prefix.nil? && sep == 'r'
779 if prefix.nil? && sep == 'r'
777 if project
780 if project
778 repository = nil
781 repository = nil
779 if repo_identifier
782 if repo_identifier
780 repository = project.repositories.detect {|repo| repo.identifier == repo_identifier}
783 repository = project.repositories.detect {|repo| repo.identifier == repo_identifier}
781 else
784 else
782 repository = project.repository
785 repository = project.repository
783 end
786 end
784 # project.changesets.visible raises an SQL error because of a double join on repositories
787 # project.changesets.visible raises an SQL error because of a double join on repositories
785 if repository &&
788 if repository &&
786 (changeset = Changeset.visible.
789 (changeset = Changeset.visible.
787 find_by_repository_id_and_revision(repository.id, identifier))
790 find_by_repository_id_and_revision(repository.id, identifier))
788 link = link_to(h("#{project_prefix}#{repo_prefix}r#{identifier}"),
791 link = link_to(h("#{project_prefix}#{repo_prefix}r#{identifier}"),
789 {:only_path => only_path, :controller => 'repositories',
792 {:only_path => only_path, :controller => 'repositories',
790 :action => 'revision', :id => project,
793 :action => 'revision', :id => project,
791 :repository_id => repository.identifier_param,
794 :repository_id => repository.identifier_param,
792 :rev => changeset.revision},
795 :rev => changeset.revision},
793 :class => 'changeset',
796 :class => 'changeset',
794 :title => truncate_single_line_raw(changeset.comments, 100))
797 :title => truncate_single_line_raw(changeset.comments, 100))
795 end
798 end
796 end
799 end
797 elsif sep == '#'
800 elsif sep == '#'
798 oid = identifier.to_i
801 oid = identifier.to_i
799 case prefix
802 case prefix
800 when nil
803 when nil
801 if oid.to_s == identifier &&
804 if oid.to_s == identifier &&
802 issue = Issue.visible.find_by_id(oid)
805 issue = Issue.visible.find_by_id(oid)
803 anchor = comment_id ? "note-#{comment_id}" : nil
806 anchor = comment_id ? "note-#{comment_id}" : nil
804 link = link_to("##{oid}#{comment_suffix}",
807 link = link_to("##{oid}#{comment_suffix}",
805 issue_url(issue, :only_path => only_path, :anchor => anchor),
808 issue_url(issue, :only_path => only_path, :anchor => anchor),
806 :class => issue.css_classes,
809 :class => issue.css_classes,
807 :title => "#{issue.tracker.name}: #{issue.subject.truncate(100)} (#{issue.status.name})")
810 :title => "#{issue.tracker.name}: #{issue.subject.truncate(100)} (#{issue.status.name})")
808 end
811 end
809 when 'document'
812 when 'document'
810 if document = Document.visible.find_by_id(oid)
813 if document = Document.visible.find_by_id(oid)
811 link = link_to(document.title, document_url(document, :only_path => only_path), :class => 'document')
814 link = link_to(document.title, document_url(document, :only_path => only_path), :class => 'document')
812 end
815 end
813 when 'version'
816 when 'version'
814 if version = Version.visible.find_by_id(oid)
817 if version = Version.visible.find_by_id(oid)
815 link = link_to(version.name, version_url(version, :only_path => only_path), :class => 'version')
818 link = link_to(version.name, version_url(version, :only_path => only_path), :class => 'version')
816 end
819 end
817 when 'message'
820 when 'message'
818 if message = Message.visible.find_by_id(oid)
821 if message = Message.visible.find_by_id(oid)
819 link = link_to_message(message, {:only_path => only_path}, :class => 'message')
822 link = link_to_message(message, {:only_path => only_path}, :class => 'message')
820 end
823 end
821 when 'forum'
824 when 'forum'
822 if board = Board.visible.find_by_id(oid)
825 if board = Board.visible.find_by_id(oid)
823 link = link_to(board.name, project_board_url(board.project, board, :only_path => only_path), :class => 'board')
826 link = link_to(board.name, project_board_url(board.project, board, :only_path => only_path), :class => 'board')
824 end
827 end
825 when 'news'
828 when 'news'
826 if news = News.visible.find_by_id(oid)
829 if news = News.visible.find_by_id(oid)
827 link = link_to(news.title, news_url(news, :only_path => only_path), :class => 'news')
830 link = link_to(news.title, news_url(news, :only_path => only_path), :class => 'news')
828 end
831 end
829 when 'project'
832 when 'project'
830 if p = Project.visible.find_by_id(oid)
833 if p = Project.visible.find_by_id(oid)
831 link = link_to_project(p, {:only_path => only_path}, :class => 'project')
834 link = link_to_project(p, {:only_path => only_path}, :class => 'project')
832 end
835 end
833 end
836 end
834 elsif sep == ':'
837 elsif sep == ':'
835 # removes the double quotes if any
838 # removes the double quotes if any
836 name = identifier.gsub(%r{^"(.*)"$}, "\\1")
839 name = identifier.gsub(%r{^"(.*)"$}, "\\1")
837 name = CGI.unescapeHTML(name)
840 name = CGI.unescapeHTML(name)
838 case prefix
841 case prefix
839 when 'document'
842 when 'document'
840 if project && document = project.documents.visible.find_by_title(name)
843 if project && document = project.documents.visible.find_by_title(name)
841 link = link_to(document.title, document_url(document, :only_path => only_path), :class => 'document')
844 link = link_to(document.title, document_url(document, :only_path => only_path), :class => 'document')
842 end
845 end
843 when 'version'
846 when 'version'
844 if project && version = project.versions.visible.find_by_name(name)
847 if project && version = project.versions.visible.find_by_name(name)
845 link = link_to(version.name, version_url(version, :only_path => only_path), :class => 'version')
848 link = link_to(version.name, version_url(version, :only_path => only_path), :class => 'version')
846 end
849 end
847 when 'forum'
850 when 'forum'
848 if project && board = project.boards.visible.find_by_name(name)
851 if project && board = project.boards.visible.find_by_name(name)
849 link = link_to(board.name, project_board_url(board.project, board, :only_path => only_path), :class => 'board')
852 link = link_to(board.name, project_board_url(board.project, board, :only_path => only_path), :class => 'board')
850 end
853 end
851 when 'news'
854 when 'news'
852 if project && news = project.news.visible.find_by_title(name)
855 if project && news = project.news.visible.find_by_title(name)
853 link = link_to(news.title, news_url(news, :only_path => only_path), :class => 'news')
856 link = link_to(news.title, news_url(news, :only_path => only_path), :class => 'news')
854 end
857 end
855 when 'commit', 'source', 'export'
858 when 'commit', 'source', 'export'
856 if project
859 if project
857 repository = nil
860 repository = nil
858 if name =~ %r{^(([a-z0-9\-_]+)\|)(.+)$}
861 if name =~ %r{^(([a-z0-9\-_]+)\|)(.+)$}
859 repo_prefix, repo_identifier, name = $1, $2, $3
862 repo_prefix, repo_identifier, name = $1, $2, $3
860 repository = project.repositories.detect {|repo| repo.identifier == repo_identifier}
863 repository = project.repositories.detect {|repo| repo.identifier == repo_identifier}
861 else
864 else
862 repository = project.repository
865 repository = project.repository
863 end
866 end
864 if prefix == 'commit'
867 if prefix == 'commit'
865 if repository && (changeset = Changeset.visible.where("repository_id = ? AND scmid LIKE ?", repository.id, "#{name}%").first)
868 if repository && (changeset = Changeset.visible.where("repository_id = ? AND scmid LIKE ?", repository.id, "#{name}%").first)
866 link = link_to h("#{project_prefix}#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.identifier},
869 link = link_to h("#{project_prefix}#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.identifier},
867 :class => 'changeset',
870 :class => 'changeset',
868 :title => truncate_single_line_raw(changeset.comments, 100)
871 :title => truncate_single_line_raw(changeset.comments, 100)
869 end
872 end
870 else
873 else
871 if repository && User.current.allowed_to?(:browse_repository, project)
874 if repository && User.current.allowed_to?(:browse_repository, project)
872 name =~ %r{^[/\\]*(.*?)(@([^/\\@]+?))?(#(L\d+))?$}
875 name =~ %r{^[/\\]*(.*?)(@([^/\\@]+?))?(#(L\d+))?$}
873 path, rev, anchor = $1, $3, $5
876 path, rev, anchor = $1, $3, $5
874 link = link_to h("#{project_prefix}#{prefix}:#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => (prefix == 'export' ? 'raw' : 'entry'), :id => project, :repository_id => repository.identifier_param,
877 link = link_to h("#{project_prefix}#{prefix}:#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => (prefix == 'export' ? 'raw' : 'entry'), :id => project, :repository_id => repository.identifier_param,
875 :path => to_path_param(path),
878 :path => to_path_param(path),
876 :rev => rev,
879 :rev => rev,
877 :anchor => anchor},
880 :anchor => anchor},
878 :class => (prefix == 'export' ? 'source download' : 'source')
881 :class => (prefix == 'export' ? 'source download' : 'source')
879 end
882 end
880 end
883 end
881 repo_prefix = nil
884 repo_prefix = nil
882 end
885 end
883 when 'attachment'
886 when 'attachment'
884 attachments = options[:attachments] || []
887 attachments = options[:attachments] || []
885 attachments += obj.attachments if obj.respond_to?(:attachments)
888 attachments += obj.attachments if obj.respond_to?(:attachments)
886 if attachments && attachment = Attachment.latest_attach(attachments, name)
889 if attachments && attachment = Attachment.latest_attach(attachments, name)
887 link = link_to_attachment(attachment, :only_path => only_path, :download => true, :class => 'attachment')
890 link = link_to_attachment(attachment, :only_path => only_path, :download => true, :class => 'attachment')
888 end
891 end
889 when 'project'
892 when 'project'
890 if p = Project.visible.where("identifier = :s OR LOWER(name) = :s", :s => name.downcase).first
893 if p = Project.visible.where("identifier = :s OR LOWER(name) = :s", :s => name.downcase).first
891 link = link_to_project(p, {:only_path => only_path}, :class => 'project')
894 link = link_to_project(p, {:only_path => only_path}, :class => 'project')
892 end
895 end
893 end
896 end
894 end
897 end
895 end
898 end
896 (leading + (link || "#{project_prefix}#{prefix}#{repo_prefix}#{sep}#{identifier}#{comment_suffix}"))
899 (leading + (link || "#{project_prefix}#{prefix}#{repo_prefix}#{sep}#{identifier}#{comment_suffix}"))
897 end
900 end
898 end
901 end
899 end
902 end
900
903
901 HEADING_RE = /(<h(\d)( [^>]+)?>(.+?)<\/h(\d)>)/i unless const_defined?(:HEADING_RE)
904 HEADING_RE = /(<h(\d)( [^>]+)?>(.+?)<\/h(\d)>)/i unless const_defined?(:HEADING_RE)
902
905
903 def parse_sections(text, project, obj, attr, only_path, options)
906 def parse_sections(text, project, obj, attr, only_path, options)
904 return unless options[:edit_section_links]
907 return unless options[:edit_section_links]
905 text.gsub!(HEADING_RE) do
908 text.gsub!(HEADING_RE) do
906 heading, level = $1, $2
909 heading, level = $1, $2
907 @current_section += 1
910 @current_section += 1
908 if @current_section > 1
911 if @current_section > 1
909 content_tag('div',
912 content_tag('div',
910 link_to(l(:button_edit_section), options[:edit_section_links].merge(:section => @current_section),
913 link_to(l(:button_edit_section), options[:edit_section_links].merge(:section => @current_section),
911 :class => 'icon-only icon-edit'),
914 :class => 'icon-only icon-edit'),
912 :class => "contextual heading-#{level}",
915 :class => "contextual heading-#{level}",
913 :title => l(:button_edit_section),
916 :title => l(:button_edit_section),
914 :id => "section-#{@current_section}") + heading.html_safe
917 :id => "section-#{@current_section}") + heading.html_safe
915 else
918 else
916 heading
919 heading
917 end
920 end
918 end
921 end
919 end
922 end
920
923
921 # Headings and TOC
924 # Headings and TOC
922 # Adds ids and links to headings unless options[:headings] is set to false
925 # Adds ids and links to headings unless options[:headings] is set to false
923 def parse_headings(text, project, obj, attr, only_path, options)
926 def parse_headings(text, project, obj, attr, only_path, options)
924 return if options[:headings] == false
927 return if options[:headings] == false
925
928
926 text.gsub!(HEADING_RE) do
929 text.gsub!(HEADING_RE) do
927 level, attrs, content = $2.to_i, $3, $4
930 level, attrs, content = $2.to_i, $3, $4
928 item = strip_tags(content).strip
931 item = strip_tags(content).strip
929 anchor = sanitize_anchor_name(item)
932 anchor = sanitize_anchor_name(item)
930 # used for single-file wiki export
933 # used for single-file wiki export
931 anchor = "#{obj.page.title}_#{anchor}" if options[:wiki_links] == :anchor && (obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version))
934 anchor = "#{obj.page.title}_#{anchor}" if options[:wiki_links] == :anchor && (obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version))
932 @heading_anchors[anchor] ||= 0
935 @heading_anchors[anchor] ||= 0
933 idx = (@heading_anchors[anchor] += 1)
936 idx = (@heading_anchors[anchor] += 1)
934 if idx > 1
937 if idx > 1
935 anchor = "#{anchor}-#{idx}"
938 anchor = "#{anchor}-#{idx}"
936 end
939 end
937 @parsed_headings << [level, anchor, item]
940 @parsed_headings << [level, anchor, item]
938 "<a name=\"#{anchor}\"></a>\n<h#{level} #{attrs}>#{content}<a href=\"##{anchor}\" class=\"wiki-anchor\">&para;</a></h#{level}>"
941 "<a name=\"#{anchor}\"></a>\n<h#{level} #{attrs}>#{content}<a href=\"##{anchor}\" class=\"wiki-anchor\">&para;</a></h#{level}>"
939 end
942 end
940 end
943 end
941
944
942 MACROS_RE = /(
945 MACROS_RE = /(
943 (!)? # escaping
946 (!)? # escaping
944 (
947 (
945 \{\{ # opening tag
948 \{\{ # opening tag
946 ([\w]+) # macro name
949 ([\w]+) # macro name
947 (\(([^\n\r]*?)\))? # optional arguments
950 (\(([^\n\r]*?)\))? # optional arguments
948 ([\n\r].*?[\n\r])? # optional block of text
951 ([\n\r].*?[\n\r])? # optional block of text
949 \}\} # closing tag
952 \}\} # closing tag
950 )
953 )
951 )/mx unless const_defined?(:MACROS_RE)
954 )/mx unless const_defined?(:MACROS_RE)
952
955
953 MACRO_SUB_RE = /(
956 MACRO_SUB_RE = /(
954 \{\{
957 \{\{
955 macro\((\d+)\)
958 macro\((\d+)\)
956 \}\}
959 \}\}
957 )/x unless const_defined?(:MACRO_SUB_RE)
960 )/x unless const_defined?(:MACRO_SUB_RE)
958
961
959 # Extracts macros from text
962 # Extracts macros from text
960 def catch_macros(text)
963 def catch_macros(text)
961 macros = {}
964 macros = {}
962 text.gsub!(MACROS_RE) do
965 text.gsub!(MACROS_RE) do
963 all, macro = $1, $4.downcase
966 all, macro = $1, $4.downcase
964 if macro_exists?(macro) || all =~ MACRO_SUB_RE
967 if macro_exists?(macro) || all =~ MACRO_SUB_RE
965 index = macros.size
968 index = macros.size
966 macros[index] = all
969 macros[index] = all
967 "{{macro(#{index})}}"
970 "{{macro(#{index})}}"
968 else
971 else
969 all
972 all
970 end
973 end
971 end
974 end
972 macros
975 macros
973 end
976 end
974
977
975 # Executes and replaces macros in text
978 # Executes and replaces macros in text
976 def inject_macros(text, obj, macros, execute=true)
979 def inject_macros(text, obj, macros, execute=true)
977 text.gsub!(MACRO_SUB_RE) do
980 text.gsub!(MACRO_SUB_RE) do
978 all, index = $1, $2.to_i
981 all, index = $1, $2.to_i
979 orig = macros.delete(index)
982 orig = macros.delete(index)
980 if execute && orig && orig =~ MACROS_RE
983 if execute && orig && orig =~ MACROS_RE
981 esc, all, macro, args, block = $2, $3, $4.downcase, $6.to_s, $7.try(:strip)
984 esc, all, macro, args, block = $2, $3, $4.downcase, $6.to_s, $7.try(:strip)
982 if esc.nil?
985 if esc.nil?
983 h(exec_macro(macro, obj, args, block) || all)
986 h(exec_macro(macro, obj, args, block) || all)
984 else
987 else
985 h(all)
988 h(all)
986 end
989 end
987 elsif orig
990 elsif orig
988 h(orig)
991 h(orig)
989 else
992 else
990 h(all)
993 h(all)
991 end
994 end
992 end
995 end
993 end
996 end
994
997
995 TOC_RE = /<p>\{\{((<|&lt;)|(>|&gt;))?toc\}\}<\/p>/i unless const_defined?(:TOC_RE)
998 TOC_RE = /<p>\{\{((<|&lt;)|(>|&gt;))?toc\}\}<\/p>/i unless const_defined?(:TOC_RE)
996
999
997 # Renders the TOC with given headings
1000 # Renders the TOC with given headings
998 def replace_toc(text, headings)
1001 def replace_toc(text, headings)
999 text.gsub!(TOC_RE) do
1002 text.gsub!(TOC_RE) do
1000 left_align, right_align = $2, $3
1003 left_align, right_align = $2, $3
1001 # Keep only the 4 first levels
1004 # Keep only the 4 first levels
1002 headings = headings.select{|level, anchor, item| level <= 4}
1005 headings = headings.select{|level, anchor, item| level <= 4}
1003 if headings.empty?
1006 if headings.empty?
1004 ''
1007 ''
1005 else
1008 else
1006 div_class = 'toc'
1009 div_class = 'toc'
1007 div_class << ' right' if right_align
1010 div_class << ' right' if right_align
1008 div_class << ' left' if left_align
1011 div_class << ' left' if left_align
1009 out = "<ul class=\"#{div_class}\"><li>"
1012 out = "<ul class=\"#{div_class}\"><li>"
1010 root = headings.map(&:first).min
1013 root = headings.map(&:first).min
1011 current = root
1014 current = root
1012 started = false
1015 started = false
1013 headings.each do |level, anchor, item|
1016 headings.each do |level, anchor, item|
1014 if level > current
1017 if level > current
1015 out << '<ul><li>' * (level - current)
1018 out << '<ul><li>' * (level - current)
1016 elsif level < current
1019 elsif level < current
1017 out << "</li></ul>\n" * (current - level) + "</li><li>"
1020 out << "</li></ul>\n" * (current - level) + "</li><li>"
1018 elsif started
1021 elsif started
1019 out << '</li><li>'
1022 out << '</li><li>'
1020 end
1023 end
1021 out << "<a href=\"##{anchor}\">#{item}</a>"
1024 out << "<a href=\"##{anchor}\">#{item}</a>"
1022 current = level
1025 current = level
1023 started = true
1026 started = true
1024 end
1027 end
1025 out << '</li></ul>' * (current - root)
1028 out << '</li></ul>' * (current - root)
1026 out << '</li></ul>'
1029 out << '</li></ul>'
1027 end
1030 end
1028 end
1031 end
1029 end
1032 end
1030
1033
1031 # Same as Rails' simple_format helper without using paragraphs
1034 # Same as Rails' simple_format helper without using paragraphs
1032 def simple_format_without_paragraph(text)
1035 def simple_format_without_paragraph(text)
1033 text.to_s.
1036 text.to_s.
1034 gsub(/\r\n?/, "\n"). # \r\n and \r -> \n
1037 gsub(/\r\n?/, "\n"). # \r\n and \r -> \n
1035 gsub(/\n\n+/, "<br /><br />"). # 2+ newline -> 2 br
1038 gsub(/\n\n+/, "<br /><br />"). # 2+ newline -> 2 br
1036 gsub(/([^\n]\n)(?=[^\n])/, '\1<br />'). # 1 newline -> br
1039 gsub(/([^\n]\n)(?=[^\n])/, '\1<br />'). # 1 newline -> br
1037 html_safe
1040 html_safe
1038 end
1041 end
1039
1042
1040 def lang_options_for_select(blank=true)
1043 def lang_options_for_select(blank=true)
1041 (blank ? [["(auto)", ""]] : []) + languages_options
1044 (blank ? [["(auto)", ""]] : []) + languages_options
1042 end
1045 end
1043
1046
1044 def labelled_form_for(*args, &proc)
1047 def labelled_form_for(*args, &proc)
1045 args << {} unless args.last.is_a?(Hash)
1048 args << {} unless args.last.is_a?(Hash)
1046 options = args.last
1049 options = args.last
1047 if args.first.is_a?(Symbol)
1050 if args.first.is_a?(Symbol)
1048 options.merge!(:as => args.shift)
1051 options.merge!(:as => args.shift)
1049 end
1052 end
1050 options.merge!({:builder => Redmine::Views::LabelledFormBuilder})
1053 options.merge!({:builder => Redmine::Views::LabelledFormBuilder})
1051 form_for(*args, &proc)
1054 form_for(*args, &proc)
1052 end
1055 end
1053
1056
1054 def labelled_fields_for(*args, &proc)
1057 def labelled_fields_for(*args, &proc)
1055 args << {} unless args.last.is_a?(Hash)
1058 args << {} unless args.last.is_a?(Hash)
1056 options = args.last
1059 options = args.last
1057 options.merge!({:builder => Redmine::Views::LabelledFormBuilder})
1060 options.merge!({:builder => Redmine::Views::LabelledFormBuilder})
1058 fields_for(*args, &proc)
1061 fields_for(*args, &proc)
1059 end
1062 end
1060
1063
1061 # Render the error messages for the given objects
1064 # Render the error messages for the given objects
1062 def error_messages_for(*objects)
1065 def error_messages_for(*objects)
1063 objects = objects.map {|o| o.is_a?(String) ? instance_variable_get("@#{o}") : o}.compact
1066 objects = objects.map {|o| o.is_a?(String) ? instance_variable_get("@#{o}") : o}.compact
1064 errors = objects.map {|o| o.errors.full_messages}.flatten
1067 errors = objects.map {|o| o.errors.full_messages}.flatten
1065 render_error_messages(errors)
1068 render_error_messages(errors)
1066 end
1069 end
1067
1070
1068 # Renders a list of error messages
1071 # Renders a list of error messages
1069 def render_error_messages(errors)
1072 def render_error_messages(errors)
1070 html = ""
1073 html = ""
1071 if errors.present?
1074 if errors.present?
1072 html << "<div id='errorExplanation'><ul>\n"
1075 html << "<div id='errorExplanation'><ul>\n"
1073 errors.each do |error|
1076 errors.each do |error|
1074 html << "<li>#{h error}</li>\n"
1077 html << "<li>#{h error}</li>\n"
1075 end
1078 end
1076 html << "</ul></div>\n"
1079 html << "</ul></div>\n"
1077 end
1080 end
1078 html.html_safe
1081 html.html_safe
1079 end
1082 end
1080
1083
1081 def delete_link(url, options={})
1084 def delete_link(url, options={})
1082 options = {
1085 options = {
1083 :method => :delete,
1086 :method => :delete,
1084 :data => {:confirm => l(:text_are_you_sure)},
1087 :data => {:confirm => l(:text_are_you_sure)},
1085 :class => 'icon icon-del'
1088 :class => 'icon icon-del'
1086 }.merge(options)
1089 }.merge(options)
1087
1090
1088 link_to l(:button_delete), url, options
1091 link_to l(:button_delete), url, options
1089 end
1092 end
1090
1093
1091 def preview_link(url, form, target='preview', options={})
1094 def preview_link(url, form, target='preview', options={})
1092 content_tag 'a', l(:label_preview), {
1095 content_tag 'a', l(:label_preview), {
1093 :href => "#",
1096 :href => "#",
1094 :onclick => %|submitPreview("#{escape_javascript url_for(url)}", "#{escape_javascript form}", "#{escape_javascript target}"); return false;|,
1097 :onclick => %|submitPreview("#{escape_javascript url_for(url)}", "#{escape_javascript form}", "#{escape_javascript target}"); return false;|,
1095 :accesskey => accesskey(:preview)
1098 :accesskey => accesskey(:preview)
1096 }.merge(options)
1099 }.merge(options)
1097 end
1100 end
1098
1101
1099 def link_to_function(name, function, html_options={})
1102 def link_to_function(name, function, html_options={})
1100 content_tag(:a, name, {:href => '#', :onclick => "#{function}; return false;"}.merge(html_options))
1103 content_tag(:a, name, {:href => '#', :onclick => "#{function}; return false;"}.merge(html_options))
1101 end
1104 end
1102
1105
1103 # Helper to render JSON in views
1106 # Helper to render JSON in views
1104 def raw_json(arg)
1107 def raw_json(arg)
1105 arg.to_json.to_s.gsub('/', '\/').html_safe
1108 arg.to_json.to_s.gsub('/', '\/').html_safe
1106 end
1109 end
1107
1110
1108 def back_url
1111 def back_url
1109 url = params[:back_url]
1112 url = params[:back_url]
1110 if url.nil? && referer = request.env['HTTP_REFERER']
1113 if url.nil? && referer = request.env['HTTP_REFERER']
1111 url = CGI.unescape(referer.to_s)
1114 url = CGI.unescape(referer.to_s)
1112 # URLs that contains the utf8=[checkmark] parameter added by Rails are
1115 # URLs that contains the utf8=[checkmark] parameter added by Rails are
1113 # parsed as invalid by URI.parse so the redirect to the back URL would
1116 # parsed as invalid by URI.parse so the redirect to the back URL would
1114 # not be accepted (ApplicationController#validate_back_url would return
1117 # not be accepted (ApplicationController#validate_back_url would return
1115 # false)
1118 # false)
1116 url.gsub!(/(\?|&)utf8=\u2713&?/, '\1')
1119 url.gsub!(/(\?|&)utf8=\u2713&?/, '\1')
1117 end
1120 end
1118 url
1121 url
1119 end
1122 end
1120
1123
1121 def back_url_hidden_field_tag
1124 def back_url_hidden_field_tag
1122 url = back_url
1125 url = back_url
1123 hidden_field_tag('back_url', url, :id => nil) unless url.blank?
1126 hidden_field_tag('back_url', url, :id => nil) unless url.blank?
1124 end
1127 end
1125
1128
1126 def check_all_links(form_name)
1129 def check_all_links(form_name)
1127 link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") +
1130 link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") +
1128 " | ".html_safe +
1131 " | ".html_safe +
1129 link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)")
1132 link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)")
1130 end
1133 end
1131
1134
1132 def toggle_checkboxes_link(selector)
1135 def toggle_checkboxes_link(selector)
1133 link_to_function '',
1136 link_to_function '',
1134 "toggleCheckboxesBySelector('#{selector}')",
1137 "toggleCheckboxesBySelector('#{selector}')",
1135 :title => "#{l(:button_check_all)} / #{l(:button_uncheck_all)}",
1138 :title => "#{l(:button_check_all)} / #{l(:button_uncheck_all)}",
1136 :class => 'toggle-checkboxes'
1139 :class => 'toggle-checkboxes'
1137 end
1140 end
1138
1141
1139 def progress_bar(pcts, options={})
1142 def progress_bar(pcts, options={})
1140 pcts = [pcts, pcts] unless pcts.is_a?(Array)
1143 pcts = [pcts, pcts] unless pcts.is_a?(Array)
1141 pcts = pcts.collect(&:round)
1144 pcts = pcts.collect(&:round)
1142 pcts[1] = pcts[1] - pcts[0]
1145 pcts[1] = pcts[1] - pcts[0]
1143 pcts << (100 - pcts[1] - pcts[0])
1146 pcts << (100 - pcts[1] - pcts[0])
1144 titles = options[:titles].to_a
1147 titles = options[:titles].to_a
1145 titles[0] = "#{pcts[0]}%" if titles[0].blank?
1148 titles[0] = "#{pcts[0]}%" if titles[0].blank?
1146 legend = options[:legend] || ''
1149 legend = options[:legend] || ''
1147 content_tag('table',
1150 content_tag('table',
1148 content_tag('tr',
1151 content_tag('tr',
1149 (pcts[0] > 0 ? content_tag('td', '', :style => "width: #{pcts[0]}%;", :class => 'closed', :title => titles[0]) : ''.html_safe) +
1152 (pcts[0] > 0 ? content_tag('td', '', :style => "width: #{pcts[0]}%;", :class => 'closed', :title => titles[0]) : ''.html_safe) +
1150 (pcts[1] > 0 ? content_tag('td', '', :style => "width: #{pcts[1]}%;", :class => 'done', :title => titles[1]) : ''.html_safe) +
1153 (pcts[1] > 0 ? content_tag('td', '', :style => "width: #{pcts[1]}%;", :class => 'done', :title => titles[1]) : ''.html_safe) +
1151 (pcts[2] > 0 ? content_tag('td', '', :style => "width: #{pcts[2]}%;", :class => 'todo', :title => titles[2]) : ''.html_safe)
1154 (pcts[2] > 0 ? content_tag('td', '', :style => "width: #{pcts[2]}%;", :class => 'todo', :title => titles[2]) : ''.html_safe)
1152 ), :class => "progress progress-#{pcts[0]}").html_safe +
1155 ), :class => "progress progress-#{pcts[0]}").html_safe +
1153 content_tag('p', legend, :class => 'percent').html_safe
1156 content_tag('p', legend, :class => 'percent').html_safe
1154 end
1157 end
1155
1158
1156 def checked_image(checked=true)
1159 def checked_image(checked=true)
1157 if checked
1160 if checked
1158 @checked_image_tag ||= content_tag(:span, nil, :class => 'icon-only icon-checked')
1161 @checked_image_tag ||= content_tag(:span, nil, :class => 'icon-only icon-checked')
1159 end
1162 end
1160 end
1163 end
1161
1164
1162 def context_menu(url)
1165 def context_menu(url)
1163 unless @context_menu_included
1166 unless @context_menu_included
1164 content_for :header_tags do
1167 content_for :header_tags do
1165 javascript_include_tag('context_menu') +
1168 javascript_include_tag('context_menu') +
1166 stylesheet_link_tag('context_menu')
1169 stylesheet_link_tag('context_menu')
1167 end
1170 end
1168 if l(:direction) == 'rtl'
1171 if l(:direction) == 'rtl'
1169 content_for :header_tags do
1172 content_for :header_tags do
1170 stylesheet_link_tag('context_menu_rtl')
1173 stylesheet_link_tag('context_menu_rtl')
1171 end
1174 end
1172 end
1175 end
1173 @context_menu_included = true
1176 @context_menu_included = true
1174 end
1177 end
1175 javascript_tag "contextMenuInit('#{ url_for(url) }')"
1178 javascript_tag "contextMenuInit('#{ url_for(url) }')"
1176 end
1179 end
1177
1180
1178 def calendar_for(field_id)
1181 def calendar_for(field_id)
1179 include_calendar_headers_tags
1182 include_calendar_headers_tags
1180 javascript_tag("$(function() { $('##{field_id}').addClass('date').datepickerFallback(datepickerOptions); });")
1183 javascript_tag("$(function() { $('##{field_id}').addClass('date').datepickerFallback(datepickerOptions); });")
1181 end
1184 end
1182
1185
1183 def include_calendar_headers_tags
1186 def include_calendar_headers_tags
1184 unless @calendar_headers_tags_included
1187 unless @calendar_headers_tags_included
1185 tags = ''.html_safe
1188 tags = ''.html_safe
1186 @calendar_headers_tags_included = true
1189 @calendar_headers_tags_included = true
1187 content_for :header_tags do
1190 content_for :header_tags do
1188 start_of_week = Setting.start_of_week
1191 start_of_week = Setting.start_of_week
1189 start_of_week = l(:general_first_day_of_week, :default => '1') if start_of_week.blank?
1192 start_of_week = l(:general_first_day_of_week, :default => '1') if start_of_week.blank?
1190 # Redmine uses 1..7 (monday..sunday) in settings and locales
1193 # Redmine uses 1..7 (monday..sunday) in settings and locales
1191 # JQuery uses 0..6 (sunday..saturday), 7 needs to be changed to 0
1194 # JQuery uses 0..6 (sunday..saturday), 7 needs to be changed to 0
1192 start_of_week = start_of_week.to_i % 7
1195 start_of_week = start_of_week.to_i % 7
1193 tags << javascript_tag(
1196 tags << javascript_tag(
1194 "var datepickerOptions={dateFormat: 'yy-mm-dd', firstDay: #{start_of_week}, " +
1197 "var datepickerOptions={dateFormat: 'yy-mm-dd', firstDay: #{start_of_week}, " +
1195 "showOn: 'button', buttonImageOnly: true, buttonImage: '" +
1198 "showOn: 'button', buttonImageOnly: true, buttonImage: '" +
1196 path_to_image('/images/calendar.png') +
1199 path_to_image('/images/calendar.png') +
1197 "', showButtonPanel: true, showWeek: true, showOtherMonths: true, " +
1200 "', showButtonPanel: true, showWeek: true, showOtherMonths: true, " +
1198 "selectOtherMonths: true, changeMonth: true, changeYear: true, " +
1201 "selectOtherMonths: true, changeMonth: true, changeYear: true, " +
1199 "beforeShow: beforeShowDatePicker};")
1202 "beforeShow: beforeShowDatePicker};")
1200 jquery_locale = l('jquery.locale', :default => current_language.to_s)
1203 jquery_locale = l('jquery.locale', :default => current_language.to_s)
1201 unless jquery_locale == 'en'
1204 unless jquery_locale == 'en'
1202 tags << javascript_include_tag("i18n/datepicker-#{jquery_locale}.js")
1205 tags << javascript_include_tag("i18n/datepicker-#{jquery_locale}.js")
1203 end
1206 end
1204 tags
1207 tags
1205 end
1208 end
1206 end
1209 end
1207 end
1210 end
1208
1211
1209 # Overrides Rails' stylesheet_link_tag with themes and plugins support.
1212 # Overrides Rails' stylesheet_link_tag with themes and plugins support.
1210 # Examples:
1213 # Examples:
1211 # stylesheet_link_tag('styles') # => picks styles.css from the current theme or defaults
1214 # stylesheet_link_tag('styles') # => picks styles.css from the current theme or defaults
1212 # stylesheet_link_tag('styles', :plugin => 'foo) # => picks styles.css from plugin's assets
1215 # stylesheet_link_tag('styles', :plugin => 'foo) # => picks styles.css from plugin's assets
1213 #
1216 #
1214 def stylesheet_link_tag(*sources)
1217 def stylesheet_link_tag(*sources)
1215 options = sources.last.is_a?(Hash) ? sources.pop : {}
1218 options = sources.last.is_a?(Hash) ? sources.pop : {}
1216 plugin = options.delete(:plugin)
1219 plugin = options.delete(:plugin)
1217 sources = sources.map do |source|
1220 sources = sources.map do |source|
1218 if plugin
1221 if plugin
1219 "/plugin_assets/#{plugin}/stylesheets/#{source}"
1222 "/plugin_assets/#{plugin}/stylesheets/#{source}"
1220 elsif current_theme && current_theme.stylesheets.include?(source)
1223 elsif current_theme && current_theme.stylesheets.include?(source)
1221 current_theme.stylesheet_path(source)
1224 current_theme.stylesheet_path(source)
1222 else
1225 else
1223 source
1226 source
1224 end
1227 end
1225 end
1228 end
1226 super *sources, options
1229 super *sources, options
1227 end
1230 end
1228
1231
1229 # Overrides Rails' image_tag with themes and plugins support.
1232 # Overrides Rails' image_tag with themes and plugins support.
1230 # Examples:
1233 # Examples:
1231 # image_tag('image.png') # => picks image.png from the current theme or defaults
1234 # image_tag('image.png') # => picks image.png from the current theme or defaults
1232 # image_tag('image.png', :plugin => 'foo) # => picks image.png from plugin's assets
1235 # image_tag('image.png', :plugin => 'foo) # => picks image.png from plugin's assets
1233 #
1236 #
1234 def image_tag(source, options={})
1237 def image_tag(source, options={})
1235 if plugin = options.delete(:plugin)
1238 if plugin = options.delete(:plugin)
1236 source = "/plugin_assets/#{plugin}/images/#{source}"
1239 source = "/plugin_assets/#{plugin}/images/#{source}"
1237 elsif current_theme && current_theme.images.include?(source)
1240 elsif current_theme && current_theme.images.include?(source)
1238 source = current_theme.image_path(source)
1241 source = current_theme.image_path(source)
1239 end
1242 end
1240 super source, options
1243 super source, options
1241 end
1244 end
1242
1245
1243 # Overrides Rails' javascript_include_tag with plugins support
1246 # Overrides Rails' javascript_include_tag with plugins support
1244 # Examples:
1247 # Examples:
1245 # javascript_include_tag('scripts') # => picks scripts.js from defaults
1248 # javascript_include_tag('scripts') # => picks scripts.js from defaults
1246 # javascript_include_tag('scripts', :plugin => 'foo) # => picks scripts.js from plugin's assets
1249 # javascript_include_tag('scripts', :plugin => 'foo) # => picks scripts.js from plugin's assets
1247 #
1250 #
1248 def javascript_include_tag(*sources)
1251 def javascript_include_tag(*sources)
1249 options = sources.last.is_a?(Hash) ? sources.pop : {}
1252 options = sources.last.is_a?(Hash) ? sources.pop : {}
1250 if plugin = options.delete(:plugin)
1253 if plugin = options.delete(:plugin)
1251 sources = sources.map do |source|
1254 sources = sources.map do |source|
1252 if plugin
1255 if plugin
1253 "/plugin_assets/#{plugin}/javascripts/#{source}"
1256 "/plugin_assets/#{plugin}/javascripts/#{source}"
1254 else
1257 else
1255 source
1258 source
1256 end
1259 end
1257 end
1260 end
1258 end
1261 end
1259 super *sources, options
1262 super *sources, options
1260 end
1263 end
1261
1264
1262 def sidebar_content?
1265 def sidebar_content?
1263 content_for?(:sidebar) || view_layouts_base_sidebar_hook_response.present?
1266 content_for?(:sidebar) || view_layouts_base_sidebar_hook_response.present?
1264 end
1267 end
1265
1268
1266 def view_layouts_base_sidebar_hook_response
1269 def view_layouts_base_sidebar_hook_response
1267 @view_layouts_base_sidebar_hook_response ||= call_hook(:view_layouts_base_sidebar)
1270 @view_layouts_base_sidebar_hook_response ||= call_hook(:view_layouts_base_sidebar)
1268 end
1271 end
1269
1272
1270 def email_delivery_enabled?
1273 def email_delivery_enabled?
1271 !!ActionMailer::Base.perform_deliveries
1274 !!ActionMailer::Base.perform_deliveries
1272 end
1275 end
1273
1276
1274 # Returns the avatar image tag for the given +user+ if avatars are enabled
1277 # Returns the avatar image tag for the given +user+ if avatars are enabled
1275 # +user+ can be a User or a string that will be scanned for an email address (eg. 'joe <joe@foo.bar>')
1278 # +user+ can be a User or a string that will be scanned for an email address (eg. 'joe <joe@foo.bar>')
1276 def avatar(user, options = { })
1279 def avatar(user, options = { })
1277 if Setting.gravatar_enabled?
1280 if Setting.gravatar_enabled?
1278 options.merge!(:default => Setting.gravatar_default)
1281 options.merge!(:default => Setting.gravatar_default)
1279 email = nil
1282 email = nil
1280 if user.respond_to?(:mail)
1283 if user.respond_to?(:mail)
1281 email = user.mail
1284 email = user.mail
1282 elsif user.to_s =~ %r{<(.+?)>}
1285 elsif user.to_s =~ %r{<(.+?)>}
1283 email = $1
1286 email = $1
1284 end
1287 end
1285 return gravatar(email.to_s.downcase, options) unless email.blank? rescue nil
1288 return gravatar(email.to_s.downcase, options) unless email.blank? rescue nil
1286 else
1289 else
1287 ''
1290 ''
1288 end
1291 end
1289 end
1292 end
1290
1293
1291 # Returns a link to edit user's avatar if avatars are enabled
1294 # Returns a link to edit user's avatar if avatars are enabled
1292 def avatar_edit_link(user, options={})
1295 def avatar_edit_link(user, options={})
1293 if Setting.gravatar_enabled?
1296 if Setting.gravatar_enabled?
1294 url = "https://gravatar.com"
1297 url = "https://gravatar.com"
1295 link_to avatar(user, {:title => l(:button_edit)}.merge(options)), url, :target => '_blank'
1298 link_to avatar(user, {:title => l(:button_edit)}.merge(options)), url, :target => '_blank'
1296 end
1299 end
1297 end
1300 end
1298
1301
1299 def sanitize_anchor_name(anchor)
1302 def sanitize_anchor_name(anchor)
1300 anchor.gsub(%r{[^\s\-\p{Word}]}, '').gsub(%r{\s+(\-+\s*)?}, '-')
1303 anchor.gsub(%r{[^\s\-\p{Word}]}, '').gsub(%r{\s+(\-+\s*)?}, '-')
1301 end
1304 end
1302
1305
1303 # Returns the javascript tags that are included in the html layout head
1306 # Returns the javascript tags that are included in the html layout head
1304 def javascript_heads
1307 def javascript_heads
1305 tags = javascript_include_tag('jquery-1.11.1-ui-1.11.0-ujs-3.1.4', 'application', 'responsive')
1308 tags = javascript_include_tag('jquery-1.11.1-ui-1.11.0-ujs-3.1.4', 'application', 'responsive')
1306 unless User.current.pref.warn_on_leaving_unsaved == '0'
1309 unless User.current.pref.warn_on_leaving_unsaved == '0'
1307 tags << "\n".html_safe + javascript_tag("$(window).load(function(){ warnLeavingUnsaved('#{escape_javascript l(:text_warn_on_leaving_unsaved)}'); });")
1310 tags << "\n".html_safe + javascript_tag("$(window).load(function(){ warnLeavingUnsaved('#{escape_javascript l(:text_warn_on_leaving_unsaved)}'); });")
1308 end
1311 end
1309 tags
1312 tags
1310 end
1313 end
1311
1314
1312 def favicon
1315 def favicon
1313 "<link rel='shortcut icon' href='#{favicon_path}' />".html_safe
1316 "<link rel='shortcut icon' href='#{favicon_path}' />".html_safe
1314 end
1317 end
1315
1318
1316 # Returns the path to the favicon
1319 # Returns the path to the favicon
1317 def favicon_path
1320 def favicon_path
1318 icon = (current_theme && current_theme.favicon?) ? current_theme.favicon_path : '/favicon.ico'
1321 icon = (current_theme && current_theme.favicon?) ? current_theme.favicon_path : '/favicon.ico'
1319 image_path(icon)
1322 image_path(icon)
1320 end
1323 end
1321
1324
1322 # Returns the full URL to the favicon
1325 # Returns the full URL to the favicon
1323 def favicon_url
1326 def favicon_url
1324 # TODO: use #image_url introduced in Rails4
1327 # TODO: use #image_url introduced in Rails4
1325 path = favicon_path
1328 path = favicon_path
1326 base = url_for(:controller => 'welcome', :action => 'index', :only_path => false)
1329 base = url_for(:controller => 'welcome', :action => 'index', :only_path => false)
1327 base.sub(%r{/+$},'') + '/' + path.sub(%r{^/+},'')
1330 base.sub(%r{/+$},'') + '/' + path.sub(%r{^/+},'')
1328 end
1331 end
1329
1332
1330 def robot_exclusion_tag
1333 def robot_exclusion_tag
1331 '<meta name="robots" content="noindex,follow,noarchive" />'.html_safe
1334 '<meta name="robots" content="noindex,follow,noarchive" />'.html_safe
1332 end
1335 end
1333
1336
1334 # Returns true if arg is expected in the API response
1337 # Returns true if arg is expected in the API response
1335 def include_in_api_response?(arg)
1338 def include_in_api_response?(arg)
1336 unless @included_in_api_response
1339 unless @included_in_api_response
1337 param = params[:include]
1340 param = params[:include]
1338 @included_in_api_response = param.is_a?(Array) ? param.collect(&:to_s) : param.to_s.split(',')
1341 @included_in_api_response = param.is_a?(Array) ? param.collect(&:to_s) : param.to_s.split(',')
1339 @included_in_api_response.collect!(&:strip)
1342 @included_in_api_response.collect!(&:strip)
1340 end
1343 end
1341 @included_in_api_response.include?(arg.to_s)
1344 @included_in_api_response.include?(arg.to_s)
1342 end
1345 end
1343
1346
1344 # Returns options or nil if nometa param or X-Redmine-Nometa header
1347 # Returns options or nil if nometa param or X-Redmine-Nometa header
1345 # was set in the request
1348 # was set in the request
1346 def api_meta(options)
1349 def api_meta(options)
1347 if params[:nometa].present? || request.headers['X-Redmine-Nometa']
1350 if params[:nometa].present? || request.headers['X-Redmine-Nometa']
1348 # compatibility mode for activeresource clients that raise
1351 # compatibility mode for activeresource clients that raise
1349 # an error when deserializing an array with attributes
1352 # an error when deserializing an array with attributes
1350 nil
1353 nil
1351 else
1354 else
1352 options
1355 options
1353 end
1356 end
1354 end
1357 end
1355
1358
1356 def generate_csv(&block)
1359 def generate_csv(&block)
1357 decimal_separator = l(:general_csv_decimal_separator)
1360 decimal_separator = l(:general_csv_decimal_separator)
1358 encoding = l(:general_csv_encoding)
1361 encoding = l(:general_csv_encoding)
1359 end
1362 end
1360
1363
1361 private
1364 private
1362
1365
1363 def wiki_helper
1366 def wiki_helper
1364 helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting)
1367 helper = Redmine::WikiFormatting.helper_for(Setting.text_formatting)
1365 extend helper
1368 extend helper
1366 return self
1369 return self
1367 end
1370 end
1368 end
1371 end
@@ -1,60 +1,64
1 # encoding: utf-8
1 # encoding: utf-8
2 #
2 #
3 # Redmine - project management software
3 # Redmine - project management software
4 # Copyright (C) 2006-2016 Jean-Philippe Lang
4 # Copyright (C) 2006-2016 Jean-Philippe Lang
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
9 # of the License, or (at your option) any later version.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
19
20 module UsersHelper
20 module UsersHelper
21 def users_status_options_for_select(selected)
21 def users_status_options_for_select(selected)
22 user_count_by_status = User.group('status').count.to_hash
22 user_count_by_status = User.group('status').count.to_hash
23 options_for_select([[l(:label_all), ''],
23 options_for_select([[l(:label_all), ''],
24 ["#{l(:status_active)} (#{user_count_by_status[1].to_i})", '1'],
24 ["#{l(:status_active)} (#{user_count_by_status[1].to_i})", '1'],
25 ["#{l(:status_registered)} (#{user_count_by_status[2].to_i})", '2'],
25 ["#{l(:status_registered)} (#{user_count_by_status[2].to_i})", '2'],
26 ["#{l(:status_locked)} (#{user_count_by_status[3].to_i})", '3']], selected.to_s)
26 ["#{l(:status_locked)} (#{user_count_by_status[3].to_i})", '3']], selected.to_s)
27 end
27 end
28
28
29 def user_mail_notification_options(user)
29 def user_mail_notification_options(user)
30 user.valid_notification_options.collect {|o| [l(o.last), o.first]}
30 user.valid_notification_options.collect {|o| [l(o.last), o.first]}
31 end
31 end
32
32
33 def textarea_font_options
34 [[l(:label_font_default), '']] + UserPreference::TEXTAREA_FONT_OPTIONS.map {|o| [l("label_font_#{o}"), o]}
35 end
36
33 def change_status_link(user)
37 def change_status_link(user)
34 url = {:controller => 'users', :action => 'update', :id => user, :page => params[:page], :status => params[:status], :tab => nil}
38 url = {:controller => 'users', :action => 'update', :id => user, :page => params[:page], :status => params[:status], :tab => nil}
35
39
36 if user.locked?
40 if user.locked?
37 link_to l(:button_unlock), url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :put, :class => 'icon icon-unlock'
41 link_to l(:button_unlock), url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :put, :class => 'icon icon-unlock'
38 elsif user.registered?
42 elsif user.registered?
39 link_to l(:button_activate), url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :put, :class => 'icon icon-unlock'
43 link_to l(:button_activate), url.merge(:user => {:status => User::STATUS_ACTIVE}), :method => :put, :class => 'icon icon-unlock'
40 elsif user != User.current
44 elsif user != User.current
41 link_to l(:button_lock), url.merge(:user => {:status => User::STATUS_LOCKED}), :method => :put, :class => 'icon icon-lock'
45 link_to l(:button_lock), url.merge(:user => {:status => User::STATUS_LOCKED}), :method => :put, :class => 'icon icon-lock'
42 end
46 end
43 end
47 end
44
48
45 def additional_emails_link(user)
49 def additional_emails_link(user)
46 if user.email_addresses.count > 1 || Setting.max_additional_emails.to_i > 0
50 if user.email_addresses.count > 1 || Setting.max_additional_emails.to_i > 0
47 link_to l(:label_email_address_plural), user_email_addresses_path(@user), :class => 'icon icon-email-add', :remote => true
51 link_to l(:label_email_address_plural), user_email_addresses_path(@user), :class => 'icon icon-email-add', :remote => true
48 end
52 end
49 end
53 end
50
54
51 def user_settings_tabs
55 def user_settings_tabs
52 tabs = [{:name => 'general', :partial => 'users/general', :label => :label_general},
56 tabs = [{:name => 'general', :partial => 'users/general', :label => :label_general},
53 {:name => 'memberships', :partial => 'users/memberships', :label => :label_project_plural}
57 {:name => 'memberships', :partial => 'users/memberships', :label => :label_project_plural}
54 ]
58 ]
55 if Group.givable.any?
59 if Group.givable.any?
56 tabs.insert 1, {:name => 'groups', :partial => 'users/groups', :label => :label_group_plural}
60 tabs.insert 1, {:name => 'groups', :partial => 'users/groups', :label => :label_group_plural}
57 end
61 end
58 tabs
62 tabs
59 end
63 end
60 end
64 end
@@ -1,79 +1,85
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class UserPreference < ActiveRecord::Base
18 class UserPreference < ActiveRecord::Base
19 include Redmine::SafeAttributes
19 include Redmine::SafeAttributes
20
20
21 belongs_to :user
21 belongs_to :user
22 serialize :others
22 serialize :others
23
23
24 attr_protected :others, :user_id
24 attr_protected :others, :user_id
25
25
26 before_save :set_others_hash
26 before_save :set_others_hash
27
27
28 safe_attributes 'hide_mail',
28 safe_attributes 'hide_mail',
29 'time_zone',
29 'time_zone',
30 'comments_sorting',
30 'comments_sorting',
31 'warn_on_leaving_unsaved',
31 'warn_on_leaving_unsaved',
32 'no_self_notified'
32 'no_self_notified',
33 'textarea_font'
34
35 TEXTAREA_FONT_OPTIONS = ['monospace', 'proportional']
33
36
34 def initialize(attributes=nil, *args)
37 def initialize(attributes=nil, *args)
35 super
38 super
36 if new_record? && !(attributes && attributes.key?(:hide_mail))
39 if new_record? && !(attributes && attributes.key?(:hide_mail))
37 self.hide_mail = Setting.default_users_hide_mail?
40 self.hide_mail = Setting.default_users_hide_mail?
38 end
41 end
39 if new_record? && !(attributes && attributes.key?(:no_self_notified))
42 if new_record? && !(attributes && attributes.key?(:no_self_notified))
40 self.no_self_notified = true
43 self.no_self_notified = true
41 end
44 end
42 self.others ||= {}
45 self.others ||= {}
43 end
46 end
44
47
45 def set_others_hash
48 def set_others_hash
46 self.others ||= {}
49 self.others ||= {}
47 end
50 end
48
51
49 def [](attr_name)
52 def [](attr_name)
50 if has_attribute? attr_name
53 if has_attribute? attr_name
51 super
54 super
52 else
55 else
53 others ? others[attr_name] : nil
56 others ? others[attr_name] : nil
54 end
57 end
55 end
58 end
56
59
57 def []=(attr_name, value)
60 def []=(attr_name, value)
58 if has_attribute? attr_name
61 if has_attribute? attr_name
59 super
62 super
60 else
63 else
61 h = (read_attribute(:others) || {}).dup
64 h = (read_attribute(:others) || {}).dup
62 h.update(attr_name => value)
65 h.update(attr_name => value)
63 write_attribute(:others, h)
66 write_attribute(:others, h)
64 value
67 value
65 end
68 end
66 end
69 end
67
70
68 def comments_sorting; self[:comments_sorting] end
71 def comments_sorting; self[:comments_sorting] end
69 def comments_sorting=(order); self[:comments_sorting]=order end
72 def comments_sorting=(order); self[:comments_sorting]=order end
70
73
71 def warn_on_leaving_unsaved; self[:warn_on_leaving_unsaved] || '1'; end
74 def warn_on_leaving_unsaved; self[:warn_on_leaving_unsaved] || '1'; end
72 def warn_on_leaving_unsaved=(value); self[:warn_on_leaving_unsaved]=value; end
75 def warn_on_leaving_unsaved=(value); self[:warn_on_leaving_unsaved]=value; end
73
76
74 def no_self_notified; (self[:no_self_notified] == true || self[:no_self_notified] == '1'); end
77 def no_self_notified; (self[:no_self_notified] == true || self[:no_self_notified] == '1'); end
75 def no_self_notified=(value); self[:no_self_notified]=value; end
78 def no_self_notified=(value); self[:no_self_notified]=value; end
76
79
77 def activity_scope; Array(self[:activity_scope]) ; end
80 def activity_scope; Array(self[:activity_scope]) ; end
78 def activity_scope=(value); self[:activity_scope]=value ; end
81 def activity_scope=(value); self[:activity_scope]=value ; end
82
83 def textarea_font; self[:textarea_font] end
84 def textarea_font=(value); self[:textarea_font]=value; end
79 end
85 end
@@ -1,6 +1,7
1 <%= labelled_fields_for :pref, @user.pref do |pref_fields| %>
1 <%= labelled_fields_for :pref, @user.pref do |pref_fields| %>
2 <p><%= pref_fields.check_box :hide_mail %></p>
2 <p><%= pref_fields.check_box :hide_mail %></p>
3 <p><%= pref_fields.time_zone_select :time_zone, nil, :include_blank => true %></p>
3 <p><%= pref_fields.time_zone_select :time_zone, nil, :include_blank => true %></p>
4 <p><%= pref_fields.select :comments_sorting, [[l(:label_chronological_order), 'asc'], [l(:label_reverse_chronological_order), 'desc']] %></p>
4 <p><%= pref_fields.select :comments_sorting, [[l(:label_chronological_order), 'asc'], [l(:label_reverse_chronological_order), 'desc']] %></p>
5 <p><%= pref_fields.check_box :warn_on_leaving_unsaved %></p>
5 <p><%= pref_fields.check_box :warn_on_leaving_unsaved %></p>
6 <p><%= pref_fields.select :textarea_font, textarea_font_options %></p>
6 <% end %>
7 <% end %>
@@ -1,1194 +1,1198
1 en:
1 en:
2 # Text direction: Left-to-Right (ltr) or Right-to-Left (rtl)
2 # Text direction: Left-to-Right (ltr) or Right-to-Left (rtl)
3 direction: ltr
3 direction: ltr
4 date:
4 date:
5 formats:
5 formats:
6 # Use the strftime parameters for formats.
6 # Use the strftime parameters for formats.
7 # When no format has been given, it uses default.
7 # When no format has been given, it uses default.
8 # You can provide other formats here if you like!
8 # You can provide other formats here if you like!
9 default: "%m/%d/%Y"
9 default: "%m/%d/%Y"
10 short: "%b %d"
10 short: "%b %d"
11 long: "%B %d, %Y"
11 long: "%B %d, %Y"
12
12
13 day_names: [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday]
13 day_names: [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday]
14 abbr_day_names: [Sun, Mon, Tue, Wed, Thu, Fri, Sat]
14 abbr_day_names: [Sun, Mon, Tue, Wed, Thu, Fri, Sat]
15
15
16 # Don't forget the nil at the beginning; there's no such thing as a 0th month
16 # Don't forget the nil at the beginning; there's no such thing as a 0th month
17 month_names: [~, January, February, March, April, May, June, July, August, September, October, November, December]
17 month_names: [~, January, February, March, April, May, June, July, August, September, October, November, December]
18 abbr_month_names: [~, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec]
18 abbr_month_names: [~, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec]
19 # Used in date_select and datime_select.
19 # Used in date_select and datime_select.
20 order:
20 order:
21 - :year
21 - :year
22 - :month
22 - :month
23 - :day
23 - :day
24
24
25 time:
25 time:
26 formats:
26 formats:
27 default: "%m/%d/%Y %I:%M %p"
27 default: "%m/%d/%Y %I:%M %p"
28 time: "%I:%M %p"
28 time: "%I:%M %p"
29 short: "%d %b %H:%M"
29 short: "%d %b %H:%M"
30 long: "%B %d, %Y %H:%M"
30 long: "%B %d, %Y %H:%M"
31 am: "am"
31 am: "am"
32 pm: "pm"
32 pm: "pm"
33
33
34 datetime:
34 datetime:
35 distance_in_words:
35 distance_in_words:
36 half_a_minute: "half a minute"
36 half_a_minute: "half a minute"
37 less_than_x_seconds:
37 less_than_x_seconds:
38 one: "less than 1 second"
38 one: "less than 1 second"
39 other: "less than %{count} seconds"
39 other: "less than %{count} seconds"
40 x_seconds:
40 x_seconds:
41 one: "1 second"
41 one: "1 second"
42 other: "%{count} seconds"
42 other: "%{count} seconds"
43 less_than_x_minutes:
43 less_than_x_minutes:
44 one: "less than a minute"
44 one: "less than a minute"
45 other: "less than %{count} minutes"
45 other: "less than %{count} minutes"
46 x_minutes:
46 x_minutes:
47 one: "1 minute"
47 one: "1 minute"
48 other: "%{count} minutes"
48 other: "%{count} minutes"
49 about_x_hours:
49 about_x_hours:
50 one: "about 1 hour"
50 one: "about 1 hour"
51 other: "about %{count} hours"
51 other: "about %{count} hours"
52 x_hours:
52 x_hours:
53 one: "1 hour"
53 one: "1 hour"
54 other: "%{count} hours"
54 other: "%{count} hours"
55 x_days:
55 x_days:
56 one: "1 day"
56 one: "1 day"
57 other: "%{count} days"
57 other: "%{count} days"
58 about_x_months:
58 about_x_months:
59 one: "about 1 month"
59 one: "about 1 month"
60 other: "about %{count} months"
60 other: "about %{count} months"
61 x_months:
61 x_months:
62 one: "1 month"
62 one: "1 month"
63 other: "%{count} months"
63 other: "%{count} months"
64 about_x_years:
64 about_x_years:
65 one: "about 1 year"
65 one: "about 1 year"
66 other: "about %{count} years"
66 other: "about %{count} years"
67 over_x_years:
67 over_x_years:
68 one: "over 1 year"
68 one: "over 1 year"
69 other: "over %{count} years"
69 other: "over %{count} years"
70 almost_x_years:
70 almost_x_years:
71 one: "almost 1 year"
71 one: "almost 1 year"
72 other: "almost %{count} years"
72 other: "almost %{count} years"
73
73
74 number:
74 number:
75 format:
75 format:
76 separator: "."
76 separator: "."
77 delimiter: ""
77 delimiter: ""
78 precision: 3
78 precision: 3
79
79
80 human:
80 human:
81 format:
81 format:
82 delimiter: ""
82 delimiter: ""
83 precision: 3
83 precision: 3
84 storage_units:
84 storage_units:
85 format: "%n %u"
85 format: "%n %u"
86 units:
86 units:
87 byte:
87 byte:
88 one: "Byte"
88 one: "Byte"
89 other: "Bytes"
89 other: "Bytes"
90 kb: "KB"
90 kb: "KB"
91 mb: "MB"
91 mb: "MB"
92 gb: "GB"
92 gb: "GB"
93 tb: "TB"
93 tb: "TB"
94
94
95 # Used in array.to_sentence.
95 # Used in array.to_sentence.
96 support:
96 support:
97 array:
97 array:
98 sentence_connector: "and"
98 sentence_connector: "and"
99 skip_last_comma: false
99 skip_last_comma: false
100
100
101 activerecord:
101 activerecord:
102 errors:
102 errors:
103 template:
103 template:
104 header:
104 header:
105 one: "1 error prohibited this %{model} from being saved"
105 one: "1 error prohibited this %{model} from being saved"
106 other: "%{count} errors prohibited this %{model} from being saved"
106 other: "%{count} errors prohibited this %{model} from being saved"
107 messages:
107 messages:
108 inclusion: "is not included in the list"
108 inclusion: "is not included in the list"
109 exclusion: "is reserved"
109 exclusion: "is reserved"
110 invalid: "is invalid"
110 invalid: "is invalid"
111 confirmation: "doesn't match confirmation"
111 confirmation: "doesn't match confirmation"
112 accepted: "must be accepted"
112 accepted: "must be accepted"
113 empty: "cannot be empty"
113 empty: "cannot be empty"
114 blank: "cannot be blank"
114 blank: "cannot be blank"
115 too_long: "is too long (maximum is %{count} characters)"
115 too_long: "is too long (maximum is %{count} characters)"
116 too_short: "is too short (minimum is %{count} characters)"
116 too_short: "is too short (minimum is %{count} characters)"
117 wrong_length: "is the wrong length (should be %{count} characters)"
117 wrong_length: "is the wrong length (should be %{count} characters)"
118 taken: "has already been taken"
118 taken: "has already been taken"
119 not_a_number: "is not a number"
119 not_a_number: "is not a number"
120 not_a_date: "is not a valid date"
120 not_a_date: "is not a valid date"
121 greater_than: "must be greater than %{count}"
121 greater_than: "must be greater than %{count}"
122 greater_than_or_equal_to: "must be greater than or equal to %{count}"
122 greater_than_or_equal_to: "must be greater than or equal to %{count}"
123 equal_to: "must be equal to %{count}"
123 equal_to: "must be equal to %{count}"
124 less_than: "must be less than %{count}"
124 less_than: "must be less than %{count}"
125 less_than_or_equal_to: "must be less than or equal to %{count}"
125 less_than_or_equal_to: "must be less than or equal to %{count}"
126 odd: "must be odd"
126 odd: "must be odd"
127 even: "must be even"
127 even: "must be even"
128 greater_than_start_date: "must be greater than start date"
128 greater_than_start_date: "must be greater than start date"
129 not_same_project: "doesn't belong to the same project"
129 not_same_project: "doesn't belong to the same project"
130 circular_dependency: "This relation would create a circular dependency"
130 circular_dependency: "This relation would create a circular dependency"
131 cant_link_an_issue_with_a_descendant: "An issue cannot be linked to one of its subtasks"
131 cant_link_an_issue_with_a_descendant: "An issue cannot be linked to one of its subtasks"
132 earlier_than_minimum_start_date: "cannot be earlier than %{date} because of preceding issues"
132 earlier_than_minimum_start_date: "cannot be earlier than %{date} because of preceding issues"
133
133
134 actionview_instancetag_blank_option: Please select
134 actionview_instancetag_blank_option: Please select
135
135
136 general_text_No: 'No'
136 general_text_No: 'No'
137 general_text_Yes: 'Yes'
137 general_text_Yes: 'Yes'
138 general_text_no: 'no'
138 general_text_no: 'no'
139 general_text_yes: 'yes'
139 general_text_yes: 'yes'
140 general_lang_name: 'English'
140 general_lang_name: 'English'
141 general_csv_separator: ','
141 general_csv_separator: ','
142 general_csv_decimal_separator: '.'
142 general_csv_decimal_separator: '.'
143 general_csv_encoding: ISO-8859-1
143 general_csv_encoding: ISO-8859-1
144 general_pdf_fontname: freesans
144 general_pdf_fontname: freesans
145 general_pdf_monospaced_fontname: freemono
145 general_pdf_monospaced_fontname: freemono
146 general_first_day_of_week: '7'
146 general_first_day_of_week: '7'
147
147
148 notice_account_updated: Account was successfully updated.
148 notice_account_updated: Account was successfully updated.
149 notice_account_invalid_credentials: Invalid user or password
149 notice_account_invalid_credentials: Invalid user or password
150 notice_account_password_updated: Password was successfully updated.
150 notice_account_password_updated: Password was successfully updated.
151 notice_account_wrong_password: Wrong password
151 notice_account_wrong_password: Wrong password
152 notice_account_register_done: Account was successfully created. An email containing the instructions to activate your account was sent to %{email}.
152 notice_account_register_done: Account was successfully created. An email containing the instructions to activate your account was sent to %{email}.
153 notice_account_unknown_email: Unknown user.
153 notice_account_unknown_email: Unknown user.
154 notice_account_not_activated_yet: You haven't activated your account yet. If you want to receive a new activation email, please <a href="%{url}">click this link</a>.
154 notice_account_not_activated_yet: You haven't activated your account yet. If you want to receive a new activation email, please <a href="%{url}">click this link</a>.
155 notice_account_locked: Your account is locked.
155 notice_account_locked: Your account is locked.
156 notice_can_t_change_password: This account uses an external authentication source. Impossible to change the password.
156 notice_can_t_change_password: This account uses an external authentication source. Impossible to change the password.
157 notice_account_lost_email_sent: An email with instructions to choose a new password has been sent to you.
157 notice_account_lost_email_sent: An email with instructions to choose a new password has been sent to you.
158 notice_account_activated: Your account has been activated. You can now log in.
158 notice_account_activated: Your account has been activated. You can now log in.
159 notice_successful_create: Successful creation.
159 notice_successful_create: Successful creation.
160 notice_successful_update: Successful update.
160 notice_successful_update: Successful update.
161 notice_successful_delete: Successful deletion.
161 notice_successful_delete: Successful deletion.
162 notice_successful_connection: Successful connection.
162 notice_successful_connection: Successful connection.
163 notice_file_not_found: The page you were trying to access doesn't exist or has been removed.
163 notice_file_not_found: The page you were trying to access doesn't exist or has been removed.
164 notice_locking_conflict: Data has been updated by another user.
164 notice_locking_conflict: Data has been updated by another user.
165 notice_not_authorized: You are not authorized to access this page.
165 notice_not_authorized: You are not authorized to access this page.
166 notice_not_authorized_archived_project: The project you're trying to access has been archived.
166 notice_not_authorized_archived_project: The project you're trying to access has been archived.
167 notice_email_sent: "An email was sent to %{value}"
167 notice_email_sent: "An email was sent to %{value}"
168 notice_email_error: "An error occurred while sending mail (%{value})"
168 notice_email_error: "An error occurred while sending mail (%{value})"
169 notice_feeds_access_key_reseted: Your Atom access key was reset.
169 notice_feeds_access_key_reseted: Your Atom access key was reset.
170 notice_api_access_key_reseted: Your API access key was reset.
170 notice_api_access_key_reseted: Your API access key was reset.
171 notice_failed_to_save_issues: "Failed to save %{count} issue(s) on %{total} selected: %{ids}."
171 notice_failed_to_save_issues: "Failed to save %{count} issue(s) on %{total} selected: %{ids}."
172 notice_failed_to_save_time_entries: "Failed to save %{count} time entrie(s) on %{total} selected: %{ids}."
172 notice_failed_to_save_time_entries: "Failed to save %{count} time entrie(s) on %{total} selected: %{ids}."
173 notice_failed_to_save_members: "Failed to save member(s): %{errors}."
173 notice_failed_to_save_members: "Failed to save member(s): %{errors}."
174 notice_no_issue_selected: "No issue is selected! Please, check the issues you want to edit."
174 notice_no_issue_selected: "No issue is selected! Please, check the issues you want to edit."
175 notice_account_pending: "Your account was created and is now pending administrator approval."
175 notice_account_pending: "Your account was created and is now pending administrator approval."
176 notice_default_data_loaded: Default configuration successfully loaded.
176 notice_default_data_loaded: Default configuration successfully loaded.
177 notice_unable_delete_version: Unable to delete version.
177 notice_unable_delete_version: Unable to delete version.
178 notice_unable_delete_time_entry: Unable to delete time log entry.
178 notice_unable_delete_time_entry: Unable to delete time log entry.
179 notice_issue_done_ratios_updated: Issue done ratios updated.
179 notice_issue_done_ratios_updated: Issue done ratios updated.
180 notice_gantt_chart_truncated: "The chart was truncated because it exceeds the maximum number of items that can be displayed (%{max})"
180 notice_gantt_chart_truncated: "The chart was truncated because it exceeds the maximum number of items that can be displayed (%{max})"
181 notice_issue_successful_create: "Issue %{id} created."
181 notice_issue_successful_create: "Issue %{id} created."
182 notice_issue_update_conflict: "The issue has been updated by an other user while you were editing it."
182 notice_issue_update_conflict: "The issue has been updated by an other user while you were editing it."
183 notice_account_deleted: "Your account has been permanently deleted."
183 notice_account_deleted: "Your account has been permanently deleted."
184 notice_user_successful_create: "User %{id} created."
184 notice_user_successful_create: "User %{id} created."
185 notice_new_password_must_be_different: The new password must be different from the current password
185 notice_new_password_must_be_different: The new password must be different from the current password
186 notice_import_finished: "%{count} items have been imported"
186 notice_import_finished: "%{count} items have been imported"
187 notice_import_finished_with_errors: "%{count} out of %{total} items could not be imported"
187 notice_import_finished_with_errors: "%{count} out of %{total} items could not be imported"
188
188
189 error_can_t_load_default_data: "Default configuration could not be loaded: %{value}"
189 error_can_t_load_default_data: "Default configuration could not be loaded: %{value}"
190 error_scm_not_found: "The entry or revision was not found in the repository."
190 error_scm_not_found: "The entry or revision was not found in the repository."
191 error_scm_command_failed: "An error occurred when trying to access the repository: %{value}"
191 error_scm_command_failed: "An error occurred when trying to access the repository: %{value}"
192 error_scm_annotate: "The entry does not exist or cannot be annotated."
192 error_scm_annotate: "The entry does not exist or cannot be annotated."
193 error_scm_annotate_big_text_file: "The entry cannot be annotated, as it exceeds the maximum text file size."
193 error_scm_annotate_big_text_file: "The entry cannot be annotated, as it exceeds the maximum text file size."
194 error_issue_not_found_in_project: 'The issue was not found or does not belong to this project'
194 error_issue_not_found_in_project: 'The issue was not found or does not belong to this project'
195 error_no_tracker_in_project: 'No tracker is associated to this project. Please check the Project settings.'
195 error_no_tracker_in_project: 'No tracker is associated to this project. Please check the Project settings.'
196 error_no_default_issue_status: 'No default issue status is defined. Please check your configuration (Go to "Administration -> Issue statuses").'
196 error_no_default_issue_status: 'No default issue status is defined. Please check your configuration (Go to "Administration -> Issue statuses").'
197 error_can_not_delete_custom_field: Unable to delete custom field
197 error_can_not_delete_custom_field: Unable to delete custom field
198 error_can_not_delete_tracker: "This tracker contains issues and cannot be deleted."
198 error_can_not_delete_tracker: "This tracker contains issues and cannot be deleted."
199 error_can_not_remove_role: "This role is in use and cannot be deleted."
199 error_can_not_remove_role: "This role is in use and cannot be deleted."
200 error_can_not_reopen_issue_on_closed_version: 'An issue assigned to a closed version cannot be reopened'
200 error_can_not_reopen_issue_on_closed_version: 'An issue assigned to a closed version cannot be reopened'
201 error_can_not_archive_project: This project cannot be archived
201 error_can_not_archive_project: This project cannot be archived
202 error_issue_done_ratios_not_updated: "Issue done ratios not updated."
202 error_issue_done_ratios_not_updated: "Issue done ratios not updated."
203 error_workflow_copy_source: 'Please select a source tracker or role'
203 error_workflow_copy_source: 'Please select a source tracker or role'
204 error_workflow_copy_target: 'Please select target tracker(s) and role(s)'
204 error_workflow_copy_target: 'Please select target tracker(s) and role(s)'
205 error_unable_delete_issue_status: 'Unable to delete issue status'
205 error_unable_delete_issue_status: 'Unable to delete issue status'
206 error_unable_to_connect: "Unable to connect (%{value})"
206 error_unable_to_connect: "Unable to connect (%{value})"
207 error_attachment_too_big: "This file cannot be uploaded because it exceeds the maximum allowed file size (%{max_size})"
207 error_attachment_too_big: "This file cannot be uploaded because it exceeds the maximum allowed file size (%{max_size})"
208 error_session_expired: "Your session has expired. Please login again."
208 error_session_expired: "Your session has expired. Please login again."
209 warning_attachments_not_saved: "%{count} file(s) could not be saved."
209 warning_attachments_not_saved: "%{count} file(s) could not be saved."
210 error_password_expired: "Your password has expired or the administrator requires you to change it."
210 error_password_expired: "Your password has expired or the administrator requires you to change it."
211 error_invalid_file_encoding: "The file is not a valid %{encoding} encoded file"
211 error_invalid_file_encoding: "The file is not a valid %{encoding} encoded file"
212 error_invalid_csv_file_or_settings: "The file is not a CSV file or does not match the settings below"
212 error_invalid_csv_file_or_settings: "The file is not a CSV file or does not match the settings below"
213 error_can_not_read_import_file: "An error occurred while reading the file to import"
213 error_can_not_read_import_file: "An error occurred while reading the file to import"
214 error_attachment_extension_not_allowed: "Attachment extension %{extension} is not allowed"
214 error_attachment_extension_not_allowed: "Attachment extension %{extension} is not allowed"
215 error_ldap_bind_credentials: "Invalid LDAP Account/Password"
215 error_ldap_bind_credentials: "Invalid LDAP Account/Password"
216 error_no_tracker_allowed_for_new_issue_in_project: "The project doesn't have any trackers for which you can create an issue"
216 error_no_tracker_allowed_for_new_issue_in_project: "The project doesn't have any trackers for which you can create an issue"
217 error_no_projects_with_tracker_allowed_for_new_issue: "There are no projects with trackers for which you can create an issue"
217 error_no_projects_with_tracker_allowed_for_new_issue: "There are no projects with trackers for which you can create an issue"
218
218
219 mail_subject_lost_password: "Your %{value} password"
219 mail_subject_lost_password: "Your %{value} password"
220 mail_body_lost_password: 'To change your password, click on the following link:'
220 mail_body_lost_password: 'To change your password, click on the following link:'
221 mail_subject_register: "Your %{value} account activation"
221 mail_subject_register: "Your %{value} account activation"
222 mail_body_register: 'To activate your account, click on the following link:'
222 mail_body_register: 'To activate your account, click on the following link:'
223 mail_body_account_information_external: "You can use your %{value} account to log in."
223 mail_body_account_information_external: "You can use your %{value} account to log in."
224 mail_body_account_information: Your account information
224 mail_body_account_information: Your account information
225 mail_subject_account_activation_request: "%{value} account activation request"
225 mail_subject_account_activation_request: "%{value} account activation request"
226 mail_body_account_activation_request: "A new user (%{value}) has registered. The account is pending your approval:"
226 mail_body_account_activation_request: "A new user (%{value}) has registered. The account is pending your approval:"
227 mail_subject_reminder: "%{count} issue(s) due in the next %{days} days"
227 mail_subject_reminder: "%{count} issue(s) due in the next %{days} days"
228 mail_body_reminder: "%{count} issue(s) that are assigned to you are due in the next %{days} days:"
228 mail_body_reminder: "%{count} issue(s) that are assigned to you are due in the next %{days} days:"
229 mail_subject_wiki_content_added: "'%{id}' wiki page has been added"
229 mail_subject_wiki_content_added: "'%{id}' wiki page has been added"
230 mail_body_wiki_content_added: "The '%{id}' wiki page has been added by %{author}."
230 mail_body_wiki_content_added: "The '%{id}' wiki page has been added by %{author}."
231 mail_subject_wiki_content_updated: "'%{id}' wiki page has been updated"
231 mail_subject_wiki_content_updated: "'%{id}' wiki page has been updated"
232 mail_body_wiki_content_updated: "The '%{id}' wiki page has been updated by %{author}."
232 mail_body_wiki_content_updated: "The '%{id}' wiki page has been updated by %{author}."
233 mail_subject_security_notification: "Security notification"
233 mail_subject_security_notification: "Security notification"
234 mail_body_security_notification_change: "%{field} was changed."
234 mail_body_security_notification_change: "%{field} was changed."
235 mail_body_security_notification_change_to: "%{field} was changed to %{value}."
235 mail_body_security_notification_change_to: "%{field} was changed to %{value}."
236 mail_body_security_notification_add: "%{field} %{value} was added."
236 mail_body_security_notification_add: "%{field} %{value} was added."
237 mail_body_security_notification_remove: "%{field} %{value} was removed."
237 mail_body_security_notification_remove: "%{field} %{value} was removed."
238 mail_body_security_notification_notify_enabled: "Email address %{value} now receives notifications."
238 mail_body_security_notification_notify_enabled: "Email address %{value} now receives notifications."
239 mail_body_security_notification_notify_disabled: "Email address %{value} no longer receives notifications."
239 mail_body_security_notification_notify_disabled: "Email address %{value} no longer receives notifications."
240 mail_body_settings_updated: "The following settings were changed:"
240 mail_body_settings_updated: "The following settings were changed:"
241 mail_body_password_updated: "Your password has been changed."
241 mail_body_password_updated: "Your password has been changed."
242
242
243 field_name: Name
243 field_name: Name
244 field_description: Description
244 field_description: Description
245 field_summary: Summary
245 field_summary: Summary
246 field_is_required: Required
246 field_is_required: Required
247 field_firstname: First name
247 field_firstname: First name
248 field_lastname: Last name
248 field_lastname: Last name
249 field_mail: Email
249 field_mail: Email
250 field_address: Email
250 field_address: Email
251 field_filename: File
251 field_filename: File
252 field_filesize: Size
252 field_filesize: Size
253 field_downloads: Downloads
253 field_downloads: Downloads
254 field_author: Author
254 field_author: Author
255 field_created_on: Created
255 field_created_on: Created
256 field_updated_on: Updated
256 field_updated_on: Updated
257 field_closed_on: Closed
257 field_closed_on: Closed
258 field_field_format: Format
258 field_field_format: Format
259 field_is_for_all: For all projects
259 field_is_for_all: For all projects
260 field_possible_values: Possible values
260 field_possible_values: Possible values
261 field_regexp: Regular expression
261 field_regexp: Regular expression
262 field_min_length: Minimum length
262 field_min_length: Minimum length
263 field_max_length: Maximum length
263 field_max_length: Maximum length
264 field_value: Value
264 field_value: Value
265 field_category: Category
265 field_category: Category
266 field_title: Title
266 field_title: Title
267 field_project: Project
267 field_project: Project
268 field_issue: Issue
268 field_issue: Issue
269 field_status: Status
269 field_status: Status
270 field_notes: Notes
270 field_notes: Notes
271 field_is_closed: Issue closed
271 field_is_closed: Issue closed
272 field_is_default: Default value
272 field_is_default: Default value
273 field_tracker: Tracker
273 field_tracker: Tracker
274 field_subject: Subject
274 field_subject: Subject
275 field_due_date: Due date
275 field_due_date: Due date
276 field_assigned_to: Assignee
276 field_assigned_to: Assignee
277 field_priority: Priority
277 field_priority: Priority
278 field_fixed_version: Target version
278 field_fixed_version: Target version
279 field_user: User
279 field_user: User
280 field_principal: Principal
280 field_principal: Principal
281 field_role: Role
281 field_role: Role
282 field_homepage: Homepage
282 field_homepage: Homepage
283 field_is_public: Public
283 field_is_public: Public
284 field_parent: Subproject of
284 field_parent: Subproject of
285 field_is_in_roadmap: Issues displayed in roadmap
285 field_is_in_roadmap: Issues displayed in roadmap
286 field_login: Login
286 field_login: Login
287 field_mail_notification: Email notifications
287 field_mail_notification: Email notifications
288 field_admin: Administrator
288 field_admin: Administrator
289 field_last_login_on: Last connection
289 field_last_login_on: Last connection
290 field_language: Language
290 field_language: Language
291 field_effective_date: Due date
291 field_effective_date: Due date
292 field_password: Password
292 field_password: Password
293 field_new_password: New password
293 field_new_password: New password
294 field_password_confirmation: Confirmation
294 field_password_confirmation: Confirmation
295 field_version: Version
295 field_version: Version
296 field_type: Type
296 field_type: Type
297 field_host: Host
297 field_host: Host
298 field_port: Port
298 field_port: Port
299 field_account: Account
299 field_account: Account
300 field_base_dn: Base DN
300 field_base_dn: Base DN
301 field_attr_login: Login attribute
301 field_attr_login: Login attribute
302 field_attr_firstname: Firstname attribute
302 field_attr_firstname: Firstname attribute
303 field_attr_lastname: Lastname attribute
303 field_attr_lastname: Lastname attribute
304 field_attr_mail: Email attribute
304 field_attr_mail: Email attribute
305 field_onthefly: On-the-fly user creation
305 field_onthefly: On-the-fly user creation
306 field_start_date: Start date
306 field_start_date: Start date
307 field_done_ratio: "% Done"
307 field_done_ratio: "% Done"
308 field_auth_source: Authentication mode
308 field_auth_source: Authentication mode
309 field_hide_mail: Hide my email address
309 field_hide_mail: Hide my email address
310 field_comments: Comment
310 field_comments: Comment
311 field_url: URL
311 field_url: URL
312 field_start_page: Start page
312 field_start_page: Start page
313 field_subproject: Subproject
313 field_subproject: Subproject
314 field_hours: Hours
314 field_hours: Hours
315 field_activity: Activity
315 field_activity: Activity
316 field_spent_on: Date
316 field_spent_on: Date
317 field_identifier: Identifier
317 field_identifier: Identifier
318 field_is_filter: Used as a filter
318 field_is_filter: Used as a filter
319 field_issue_to: Related issue
319 field_issue_to: Related issue
320 field_delay: Delay
320 field_delay: Delay
321 field_assignable: Issues can be assigned to this role
321 field_assignable: Issues can be assigned to this role
322 field_redirect_existing_links: Redirect existing links
322 field_redirect_existing_links: Redirect existing links
323 field_estimated_hours: Estimated time
323 field_estimated_hours: Estimated time
324 field_column_names: Columns
324 field_column_names: Columns
325 field_time_entries: Log time
325 field_time_entries: Log time
326 field_time_zone: Time zone
326 field_time_zone: Time zone
327 field_searchable: Searchable
327 field_searchable: Searchable
328 field_default_value: Default value
328 field_default_value: Default value
329 field_comments_sorting: Display comments
329 field_comments_sorting: Display comments
330 field_parent_title: Parent page
330 field_parent_title: Parent page
331 field_editable: Editable
331 field_editable: Editable
332 field_watcher: Watcher
332 field_watcher: Watcher
333 field_identity_url: OpenID URL
333 field_identity_url: OpenID URL
334 field_content: Content
334 field_content: Content
335 field_group_by: Group results by
335 field_group_by: Group results by
336 field_sharing: Sharing
336 field_sharing: Sharing
337 field_parent_issue: Parent task
337 field_parent_issue: Parent task
338 field_member_of_group: "Assignee's group"
338 field_member_of_group: "Assignee's group"
339 field_assigned_to_role: "Assignee's role"
339 field_assigned_to_role: "Assignee's role"
340 field_text: Text field
340 field_text: Text field
341 field_visible: Visible
341 field_visible: Visible
342 field_warn_on_leaving_unsaved: "Warn me when leaving a page with unsaved text"
342 field_warn_on_leaving_unsaved: "Warn me when leaving a page with unsaved text"
343 field_issues_visibility: Issues visibility
343 field_issues_visibility: Issues visibility
344 field_is_private: Private
344 field_is_private: Private
345 field_commit_logs_encoding: Commit messages encoding
345 field_commit_logs_encoding: Commit messages encoding
346 field_scm_path_encoding: Path encoding
346 field_scm_path_encoding: Path encoding
347 field_path_to_repository: Path to repository
347 field_path_to_repository: Path to repository
348 field_root_directory: Root directory
348 field_root_directory: Root directory
349 field_cvsroot: CVSROOT
349 field_cvsroot: CVSROOT
350 field_cvs_module: Module
350 field_cvs_module: Module
351 field_repository_is_default: Main repository
351 field_repository_is_default: Main repository
352 field_multiple: Multiple values
352 field_multiple: Multiple values
353 field_auth_source_ldap_filter: LDAP filter
353 field_auth_source_ldap_filter: LDAP filter
354 field_core_fields: Standard fields
354 field_core_fields: Standard fields
355 field_timeout: "Timeout (in seconds)"
355 field_timeout: "Timeout (in seconds)"
356 field_board_parent: Parent forum
356 field_board_parent: Parent forum
357 field_private_notes: Private notes
357 field_private_notes: Private notes
358 field_inherit_members: Inherit members
358 field_inherit_members: Inherit members
359 field_generate_password: Generate password
359 field_generate_password: Generate password
360 field_must_change_passwd: Must change password at next logon
360 field_must_change_passwd: Must change password at next logon
361 field_default_status: Default status
361 field_default_status: Default status
362 field_users_visibility: Users visibility
362 field_users_visibility: Users visibility
363 field_time_entries_visibility: Time logs visibility
363 field_time_entries_visibility: Time logs visibility
364 field_total_estimated_hours: Total estimated time
364 field_total_estimated_hours: Total estimated time
365 field_default_version: Default version
365 field_default_version: Default version
366 field_remote_ip: IP address
366 field_remote_ip: IP address
367 field_textarea_font: Font used for text areas
367
368
368 setting_app_title: Application title
369 setting_app_title: Application title
369 setting_app_subtitle: Application subtitle
370 setting_app_subtitle: Application subtitle
370 setting_welcome_text: Welcome text
371 setting_welcome_text: Welcome text
371 setting_default_language: Default language
372 setting_default_language: Default language
372 setting_login_required: Authentication required
373 setting_login_required: Authentication required
373 setting_self_registration: Self-registration
374 setting_self_registration: Self-registration
374 setting_attachment_max_size: Maximum attachment size
375 setting_attachment_max_size: Maximum attachment size
375 setting_issues_export_limit: Issues export limit
376 setting_issues_export_limit: Issues export limit
376 setting_mail_from: Emission email address
377 setting_mail_from: Emission email address
377 setting_bcc_recipients: Blind carbon copy recipients (bcc)
378 setting_bcc_recipients: Blind carbon copy recipients (bcc)
378 setting_plain_text_mail: Plain text mail (no HTML)
379 setting_plain_text_mail: Plain text mail (no HTML)
379 setting_host_name: Host name and path
380 setting_host_name: Host name and path
380 setting_text_formatting: Text formatting
381 setting_text_formatting: Text formatting
381 setting_wiki_compression: Wiki history compression
382 setting_wiki_compression: Wiki history compression
382 setting_feeds_limit: Maximum number of items in Atom feeds
383 setting_feeds_limit: Maximum number of items in Atom feeds
383 setting_default_projects_public: New projects are public by default
384 setting_default_projects_public: New projects are public by default
384 setting_autofetch_changesets: Fetch commits automatically
385 setting_autofetch_changesets: Fetch commits automatically
385 setting_sys_api_enabled: Enable WS for repository management
386 setting_sys_api_enabled: Enable WS for repository management
386 setting_commit_ref_keywords: Referencing keywords
387 setting_commit_ref_keywords: Referencing keywords
387 setting_commit_fix_keywords: Fixing keywords
388 setting_commit_fix_keywords: Fixing keywords
388 setting_autologin: Autologin
389 setting_autologin: Autologin
389 setting_date_format: Date format
390 setting_date_format: Date format
390 setting_time_format: Time format
391 setting_time_format: Time format
391 setting_cross_project_issue_relations: Allow cross-project issue relations
392 setting_cross_project_issue_relations: Allow cross-project issue relations
392 setting_cross_project_subtasks: Allow cross-project subtasks
393 setting_cross_project_subtasks: Allow cross-project subtasks
393 setting_issue_list_default_columns: Default columns displayed on the issue list
394 setting_issue_list_default_columns: Default columns displayed on the issue list
394 setting_repositories_encodings: Attachments and repositories encodings
395 setting_repositories_encodings: Attachments and repositories encodings
395 setting_emails_header: Email header
396 setting_emails_header: Email header
396 setting_emails_footer: Email footer
397 setting_emails_footer: Email footer
397 setting_protocol: Protocol
398 setting_protocol: Protocol
398 setting_per_page_options: Objects per page options
399 setting_per_page_options: Objects per page options
399 setting_user_format: Users display format
400 setting_user_format: Users display format
400 setting_activity_days_default: Days displayed on project activity
401 setting_activity_days_default: Days displayed on project activity
401 setting_display_subprojects_issues: Display subprojects issues on main projects by default
402 setting_display_subprojects_issues: Display subprojects issues on main projects by default
402 setting_enabled_scm: Enabled SCM
403 setting_enabled_scm: Enabled SCM
403 setting_mail_handler_body_delimiters: "Truncate emails after one of these lines"
404 setting_mail_handler_body_delimiters: "Truncate emails after one of these lines"
404 setting_mail_handler_api_enabled: Enable WS for incoming emails
405 setting_mail_handler_api_enabled: Enable WS for incoming emails
405 setting_mail_handler_api_key: Incoming email WS API key
406 setting_mail_handler_api_key: Incoming email WS API key
406 setting_sys_api_key: Repository management WS API key
407 setting_sys_api_key: Repository management WS API key
407 setting_sequential_project_identifiers: Generate sequential project identifiers
408 setting_sequential_project_identifiers: Generate sequential project identifiers
408 setting_gravatar_enabled: Use Gravatar user icons
409 setting_gravatar_enabled: Use Gravatar user icons
409 setting_gravatar_default: Default Gravatar image
410 setting_gravatar_default: Default Gravatar image
410 setting_diff_max_lines_displayed: Maximum number of diff lines displayed
411 setting_diff_max_lines_displayed: Maximum number of diff lines displayed
411 setting_file_max_size_displayed: Maximum size of text files displayed inline
412 setting_file_max_size_displayed: Maximum size of text files displayed inline
412 setting_repository_log_display_limit: Maximum number of revisions displayed on file log
413 setting_repository_log_display_limit: Maximum number of revisions displayed on file log
413 setting_openid: Allow OpenID login and registration
414 setting_openid: Allow OpenID login and registration
414 setting_password_max_age: Require password change after
415 setting_password_max_age: Require password change after
415 setting_password_min_length: Minimum password length
416 setting_password_min_length: Minimum password length
416 setting_lost_password: Allow password reset via email
417 setting_lost_password: Allow password reset via email
417 setting_new_project_user_role_id: Role given to a non-admin user who creates a project
418 setting_new_project_user_role_id: Role given to a non-admin user who creates a project
418 setting_default_projects_modules: Default enabled modules for new projects
419 setting_default_projects_modules: Default enabled modules for new projects
419 setting_issue_done_ratio: Calculate the issue done ratio with
420 setting_issue_done_ratio: Calculate the issue done ratio with
420 setting_issue_done_ratio_issue_field: Use the issue field
421 setting_issue_done_ratio_issue_field: Use the issue field
421 setting_issue_done_ratio_issue_status: Use the issue status
422 setting_issue_done_ratio_issue_status: Use the issue status
422 setting_start_of_week: Start calendars on
423 setting_start_of_week: Start calendars on
423 setting_rest_api_enabled: Enable REST web service
424 setting_rest_api_enabled: Enable REST web service
424 setting_cache_formatted_text: Cache formatted text
425 setting_cache_formatted_text: Cache formatted text
425 setting_default_notification_option: Default notification option
426 setting_default_notification_option: Default notification option
426 setting_commit_logtime_enabled: Enable time logging
427 setting_commit_logtime_enabled: Enable time logging
427 setting_commit_logtime_activity_id: Activity for logged time
428 setting_commit_logtime_activity_id: Activity for logged time
428 setting_gantt_items_limit: Maximum number of items displayed on the gantt chart
429 setting_gantt_items_limit: Maximum number of items displayed on the gantt chart
429 setting_issue_group_assignment: Allow issue assignment to groups
430 setting_issue_group_assignment: Allow issue assignment to groups
430 setting_default_issue_start_date_to_creation_date: Use current date as start date for new issues
431 setting_default_issue_start_date_to_creation_date: Use current date as start date for new issues
431 setting_commit_cross_project_ref: Allow issues of all the other projects to be referenced and fixed
432 setting_commit_cross_project_ref: Allow issues of all the other projects to be referenced and fixed
432 setting_unsubscribe: Allow users to delete their own account
433 setting_unsubscribe: Allow users to delete their own account
433 setting_session_lifetime: Session maximum lifetime
434 setting_session_lifetime: Session maximum lifetime
434 setting_session_timeout: Session inactivity timeout
435 setting_session_timeout: Session inactivity timeout
435 setting_thumbnails_enabled: Display attachment thumbnails
436 setting_thumbnails_enabled: Display attachment thumbnails
436 setting_thumbnails_size: Thumbnails size (in pixels)
437 setting_thumbnails_size: Thumbnails size (in pixels)
437 setting_non_working_week_days: Non-working days
438 setting_non_working_week_days: Non-working days
438 setting_jsonp_enabled: Enable JSONP support
439 setting_jsonp_enabled: Enable JSONP support
439 setting_default_projects_tracker_ids: Default trackers for new projects
440 setting_default_projects_tracker_ids: Default trackers for new projects
440 setting_mail_handler_excluded_filenames: Exclude attachments by name
441 setting_mail_handler_excluded_filenames: Exclude attachments by name
441 setting_force_default_language_for_anonymous: Force default language for anonymous users
442 setting_force_default_language_for_anonymous: Force default language for anonymous users
442 setting_force_default_language_for_loggedin: Force default language for logged-in users
443 setting_force_default_language_for_loggedin: Force default language for logged-in users
443 setting_link_copied_issue: Link issues on copy
444 setting_link_copied_issue: Link issues on copy
444 setting_max_additional_emails: Maximum number of additional email addresses
445 setting_max_additional_emails: Maximum number of additional email addresses
445 setting_search_results_per_page: Search results per page
446 setting_search_results_per_page: Search results per page
446 setting_attachment_extensions_allowed: Allowed extensions
447 setting_attachment_extensions_allowed: Allowed extensions
447 setting_attachment_extensions_denied: Disallowed extensions
448 setting_attachment_extensions_denied: Disallowed extensions
448 setting_new_item_menu_tab: Project menu tab for creating new objects
449 setting_new_item_menu_tab: Project menu tab for creating new objects
449
450
450 permission_add_project: Create project
451 permission_add_project: Create project
451 permission_add_subprojects: Create subprojects
452 permission_add_subprojects: Create subprojects
452 permission_edit_project: Edit project
453 permission_edit_project: Edit project
453 permission_close_project: Close / reopen the project
454 permission_close_project: Close / reopen the project
454 permission_select_project_modules: Select project modules
455 permission_select_project_modules: Select project modules
455 permission_manage_members: Manage members
456 permission_manage_members: Manage members
456 permission_manage_project_activities: Manage project activities
457 permission_manage_project_activities: Manage project activities
457 permission_manage_versions: Manage versions
458 permission_manage_versions: Manage versions
458 permission_manage_categories: Manage issue categories
459 permission_manage_categories: Manage issue categories
459 permission_view_issues: View Issues
460 permission_view_issues: View Issues
460 permission_add_issues: Add issues
461 permission_add_issues: Add issues
461 permission_edit_issues: Edit issues
462 permission_edit_issues: Edit issues
462 permission_copy_issues: Copy issues
463 permission_copy_issues: Copy issues
463 permission_manage_issue_relations: Manage issue relations
464 permission_manage_issue_relations: Manage issue relations
464 permission_set_issues_private: Set issues public or private
465 permission_set_issues_private: Set issues public or private
465 permission_set_own_issues_private: Set own issues public or private
466 permission_set_own_issues_private: Set own issues public or private
466 permission_add_issue_notes: Add notes
467 permission_add_issue_notes: Add notes
467 permission_edit_issue_notes: Edit notes
468 permission_edit_issue_notes: Edit notes
468 permission_edit_own_issue_notes: Edit own notes
469 permission_edit_own_issue_notes: Edit own notes
469 permission_view_private_notes: View private notes
470 permission_view_private_notes: View private notes
470 permission_set_notes_private: Set notes as private
471 permission_set_notes_private: Set notes as private
471 permission_move_issues: Move issues
472 permission_move_issues: Move issues
472 permission_delete_issues: Delete issues
473 permission_delete_issues: Delete issues
473 permission_manage_public_queries: Manage public queries
474 permission_manage_public_queries: Manage public queries
474 permission_save_queries: Save queries
475 permission_save_queries: Save queries
475 permission_view_gantt: View gantt chart
476 permission_view_gantt: View gantt chart
476 permission_view_calendar: View calendar
477 permission_view_calendar: View calendar
477 permission_view_issue_watchers: View watchers list
478 permission_view_issue_watchers: View watchers list
478 permission_add_issue_watchers: Add watchers
479 permission_add_issue_watchers: Add watchers
479 permission_delete_issue_watchers: Delete watchers
480 permission_delete_issue_watchers: Delete watchers
480 permission_log_time: Log spent time
481 permission_log_time: Log spent time
481 permission_view_time_entries: View spent time
482 permission_view_time_entries: View spent time
482 permission_edit_time_entries: Edit time logs
483 permission_edit_time_entries: Edit time logs
483 permission_edit_own_time_entries: Edit own time logs
484 permission_edit_own_time_entries: Edit own time logs
484 permission_manage_news: Manage news
485 permission_manage_news: Manage news
485 permission_comment_news: Comment news
486 permission_comment_news: Comment news
486 permission_view_documents: View documents
487 permission_view_documents: View documents
487 permission_add_documents: Add documents
488 permission_add_documents: Add documents
488 permission_edit_documents: Edit documents
489 permission_edit_documents: Edit documents
489 permission_delete_documents: Delete documents
490 permission_delete_documents: Delete documents
490 permission_manage_files: Manage files
491 permission_manage_files: Manage files
491 permission_view_files: View files
492 permission_view_files: View files
492 permission_manage_wiki: Manage wiki
493 permission_manage_wiki: Manage wiki
493 permission_rename_wiki_pages: Rename wiki pages
494 permission_rename_wiki_pages: Rename wiki pages
494 permission_delete_wiki_pages: Delete wiki pages
495 permission_delete_wiki_pages: Delete wiki pages
495 permission_view_wiki_pages: View wiki
496 permission_view_wiki_pages: View wiki
496 permission_view_wiki_edits: View wiki history
497 permission_view_wiki_edits: View wiki history
497 permission_edit_wiki_pages: Edit wiki pages
498 permission_edit_wiki_pages: Edit wiki pages
498 permission_delete_wiki_pages_attachments: Delete attachments
499 permission_delete_wiki_pages_attachments: Delete attachments
499 permission_protect_wiki_pages: Protect wiki pages
500 permission_protect_wiki_pages: Protect wiki pages
500 permission_manage_repository: Manage repository
501 permission_manage_repository: Manage repository
501 permission_browse_repository: Browse repository
502 permission_browse_repository: Browse repository
502 permission_view_changesets: View changesets
503 permission_view_changesets: View changesets
503 permission_commit_access: Commit access
504 permission_commit_access: Commit access
504 permission_manage_boards: Manage forums
505 permission_manage_boards: Manage forums
505 permission_view_messages: View messages
506 permission_view_messages: View messages
506 permission_add_messages: Post messages
507 permission_add_messages: Post messages
507 permission_edit_messages: Edit messages
508 permission_edit_messages: Edit messages
508 permission_edit_own_messages: Edit own messages
509 permission_edit_own_messages: Edit own messages
509 permission_delete_messages: Delete messages
510 permission_delete_messages: Delete messages
510 permission_delete_own_messages: Delete own messages
511 permission_delete_own_messages: Delete own messages
511 permission_export_wiki_pages: Export wiki pages
512 permission_export_wiki_pages: Export wiki pages
512 permission_manage_subtasks: Manage subtasks
513 permission_manage_subtasks: Manage subtasks
513 permission_manage_related_issues: Manage related issues
514 permission_manage_related_issues: Manage related issues
514 permission_import_issues: Import issues
515 permission_import_issues: Import issues
515
516
516 project_module_issue_tracking: Issue tracking
517 project_module_issue_tracking: Issue tracking
517 project_module_time_tracking: Time tracking
518 project_module_time_tracking: Time tracking
518 project_module_news: News
519 project_module_news: News
519 project_module_documents: Documents
520 project_module_documents: Documents
520 project_module_files: Files
521 project_module_files: Files
521 project_module_wiki: Wiki
522 project_module_wiki: Wiki
522 project_module_repository: Repository
523 project_module_repository: Repository
523 project_module_boards: Forums
524 project_module_boards: Forums
524 project_module_calendar: Calendar
525 project_module_calendar: Calendar
525 project_module_gantt: Gantt
526 project_module_gantt: Gantt
526
527
527 label_user: User
528 label_user: User
528 label_user_plural: Users
529 label_user_plural: Users
529 label_user_new: New user
530 label_user_new: New user
530 label_user_anonymous: Anonymous
531 label_user_anonymous: Anonymous
531 label_project: Project
532 label_project: Project
532 label_project_new: New project
533 label_project_new: New project
533 label_project_plural: Projects
534 label_project_plural: Projects
534 label_x_projects:
535 label_x_projects:
535 zero: no projects
536 zero: no projects
536 one: 1 project
537 one: 1 project
537 other: "%{count} projects"
538 other: "%{count} projects"
538 label_project_all: All Projects
539 label_project_all: All Projects
539 label_project_latest: Latest projects
540 label_project_latest: Latest projects
540 label_issue: Issue
541 label_issue: Issue
541 label_issue_new: New issue
542 label_issue_new: New issue
542 label_issue_plural: Issues
543 label_issue_plural: Issues
543 label_issue_view_all: View all issues
544 label_issue_view_all: View all issues
544 label_issues_by: "Issues by %{value}"
545 label_issues_by: "Issues by %{value}"
545 label_issue_added: Issue added
546 label_issue_added: Issue added
546 label_issue_updated: Issue updated
547 label_issue_updated: Issue updated
547 label_issue_note_added: Note added
548 label_issue_note_added: Note added
548 label_issue_status_updated: Status updated
549 label_issue_status_updated: Status updated
549 label_issue_assigned_to_updated: Assignee updated
550 label_issue_assigned_to_updated: Assignee updated
550 label_issue_priority_updated: Priority updated
551 label_issue_priority_updated: Priority updated
551 label_document: Document
552 label_document: Document
552 label_document_new: New document
553 label_document_new: New document
553 label_document_plural: Documents
554 label_document_plural: Documents
554 label_document_added: Document added
555 label_document_added: Document added
555 label_role: Role
556 label_role: Role
556 label_role_plural: Roles
557 label_role_plural: Roles
557 label_role_new: New role
558 label_role_new: New role
558 label_role_and_permissions: Roles and permissions
559 label_role_and_permissions: Roles and permissions
559 label_role_anonymous: Anonymous
560 label_role_anonymous: Anonymous
560 label_role_non_member: Non member
561 label_role_non_member: Non member
561 label_member: Member
562 label_member: Member
562 label_member_new: New member
563 label_member_new: New member
563 label_member_plural: Members
564 label_member_plural: Members
564 label_tracker: Tracker
565 label_tracker: Tracker
565 label_tracker_plural: Trackers
566 label_tracker_plural: Trackers
566 label_tracker_all: All trackers
567 label_tracker_all: All trackers
567 label_tracker_new: New tracker
568 label_tracker_new: New tracker
568 label_workflow: Workflow
569 label_workflow: Workflow
569 label_issue_status: Issue status
570 label_issue_status: Issue status
570 label_issue_status_plural: Issue statuses
571 label_issue_status_plural: Issue statuses
571 label_issue_status_new: New status
572 label_issue_status_new: New status
572 label_issue_category: Issue category
573 label_issue_category: Issue category
573 label_issue_category_plural: Issue categories
574 label_issue_category_plural: Issue categories
574 label_issue_category_new: New category
575 label_issue_category_new: New category
575 label_custom_field: Custom field
576 label_custom_field: Custom field
576 label_custom_field_plural: Custom fields
577 label_custom_field_plural: Custom fields
577 label_custom_field_new: New custom field
578 label_custom_field_new: New custom field
578 label_enumerations: Enumerations
579 label_enumerations: Enumerations
579 label_enumeration_new: New value
580 label_enumeration_new: New value
580 label_information: Information
581 label_information: Information
581 label_information_plural: Information
582 label_information_plural: Information
582 label_please_login: Please log in
583 label_please_login: Please log in
583 label_register: Register
584 label_register: Register
584 label_login_with_open_id_option: or login with OpenID
585 label_login_with_open_id_option: or login with OpenID
585 label_password_lost: Lost password
586 label_password_lost: Lost password
586 label_password_required: Confirm your password to continue
587 label_password_required: Confirm your password to continue
587 label_home: Home
588 label_home: Home
588 label_my_page: My page
589 label_my_page: My page
589 label_my_account: My account
590 label_my_account: My account
590 label_my_projects: My projects
591 label_my_projects: My projects
591 label_my_page_block: My page block
592 label_my_page_block: My page block
592 label_administration: Administration
593 label_administration: Administration
593 label_login: Sign in
594 label_login: Sign in
594 label_logout: Sign out
595 label_logout: Sign out
595 label_help: Help
596 label_help: Help
596 label_reported_issues: Reported issues
597 label_reported_issues: Reported issues
597 label_assigned_issues: Assigned issues
598 label_assigned_issues: Assigned issues
598 label_assigned_to_me_issues: Issues assigned to me
599 label_assigned_to_me_issues: Issues assigned to me
599 label_last_login: Last connection
600 label_last_login: Last connection
600 label_registered_on: Registered on
601 label_registered_on: Registered on
601 label_activity: Activity
602 label_activity: Activity
602 label_overall_activity: Overall activity
603 label_overall_activity: Overall activity
603 label_user_activity: "%{value}'s activity"
604 label_user_activity: "%{value}'s activity"
604 label_new: New
605 label_new: New
605 label_logged_as: Logged in as
606 label_logged_as: Logged in as
606 label_environment: Environment
607 label_environment: Environment
607 label_authentication: Authentication
608 label_authentication: Authentication
608 label_auth_source: Authentication mode
609 label_auth_source: Authentication mode
609 label_auth_source_new: New authentication mode
610 label_auth_source_new: New authentication mode
610 label_auth_source_plural: Authentication modes
611 label_auth_source_plural: Authentication modes
611 label_subproject_plural: Subprojects
612 label_subproject_plural: Subprojects
612 label_subproject_new: New subproject
613 label_subproject_new: New subproject
613 label_and_its_subprojects: "%{value} and its subprojects"
614 label_and_its_subprojects: "%{value} and its subprojects"
614 label_min_max_length: Min - Max length
615 label_min_max_length: Min - Max length
615 label_list: List
616 label_list: List
616 label_date: Date
617 label_date: Date
617 label_integer: Integer
618 label_integer: Integer
618 label_float: Float
619 label_float: Float
619 label_boolean: Boolean
620 label_boolean: Boolean
620 label_string: Text
621 label_string: Text
621 label_text: Long text
622 label_text: Long text
622 label_attribute: Attribute
623 label_attribute: Attribute
623 label_attribute_plural: Attributes
624 label_attribute_plural: Attributes
624 label_no_data: No data to display
625 label_no_data: No data to display
625 label_no_preview: No preview available
626 label_no_preview: No preview available
626 label_change_status: Change status
627 label_change_status: Change status
627 label_history: History
628 label_history: History
628 label_attachment: File
629 label_attachment: File
629 label_attachment_new: New file
630 label_attachment_new: New file
630 label_attachment_delete: Delete file
631 label_attachment_delete: Delete file
631 label_attachment_plural: Files
632 label_attachment_plural: Files
632 label_file_added: File added
633 label_file_added: File added
633 label_report: Report
634 label_report: Report
634 label_report_plural: Reports
635 label_report_plural: Reports
635 label_news: News
636 label_news: News
636 label_news_new: Add news
637 label_news_new: Add news
637 label_news_plural: News
638 label_news_plural: News
638 label_news_latest: Latest news
639 label_news_latest: Latest news
639 label_news_view_all: View all news
640 label_news_view_all: View all news
640 label_news_added: News added
641 label_news_added: News added
641 label_news_comment_added: Comment added to a news
642 label_news_comment_added: Comment added to a news
642 label_settings: Settings
643 label_settings: Settings
643 label_overview: Overview
644 label_overview: Overview
644 label_version: Version
645 label_version: Version
645 label_version_new: New version
646 label_version_new: New version
646 label_version_plural: Versions
647 label_version_plural: Versions
647 label_close_versions: Close completed versions
648 label_close_versions: Close completed versions
648 label_confirmation: Confirmation
649 label_confirmation: Confirmation
649 label_export_to: 'Also available in:'
650 label_export_to: 'Also available in:'
650 label_read: Read...
651 label_read: Read...
651 label_public_projects: Public projects
652 label_public_projects: Public projects
652 label_open_issues: open
653 label_open_issues: open
653 label_open_issues_plural: open
654 label_open_issues_plural: open
654 label_closed_issues: closed
655 label_closed_issues: closed
655 label_closed_issues_plural: closed
656 label_closed_issues_plural: closed
656 label_x_open_issues_abbr:
657 label_x_open_issues_abbr:
657 zero: 0 open
658 zero: 0 open
658 one: 1 open
659 one: 1 open
659 other: "%{count} open"
660 other: "%{count} open"
660 label_x_closed_issues_abbr:
661 label_x_closed_issues_abbr:
661 zero: 0 closed
662 zero: 0 closed
662 one: 1 closed
663 one: 1 closed
663 other: "%{count} closed"
664 other: "%{count} closed"
664 label_x_issues:
665 label_x_issues:
665 zero: 0 issues
666 zero: 0 issues
666 one: 1 issue
667 one: 1 issue
667 other: "%{count} issues"
668 other: "%{count} issues"
668 label_total: Total
669 label_total: Total
669 label_total_plural: Totals
670 label_total_plural: Totals
670 label_total_time: Total time
671 label_total_time: Total time
671 label_permissions: Permissions
672 label_permissions: Permissions
672 label_current_status: Current status
673 label_current_status: Current status
673 label_new_statuses_allowed: New statuses allowed
674 label_new_statuses_allowed: New statuses allowed
674 label_all: all
675 label_all: all
675 label_any: any
676 label_any: any
676 label_none: none
677 label_none: none
677 label_nobody: nobody
678 label_nobody: nobody
678 label_next: Next
679 label_next: Next
679 label_previous: Previous
680 label_previous: Previous
680 label_used_by: Used by
681 label_used_by: Used by
681 label_details: Details
682 label_details: Details
682 label_add_note: Add a note
683 label_add_note: Add a note
683 label_calendar: Calendar
684 label_calendar: Calendar
684 label_months_from: months from
685 label_months_from: months from
685 label_gantt: Gantt
686 label_gantt: Gantt
686 label_internal: Internal
687 label_internal: Internal
687 label_last_changes: "last %{count} changes"
688 label_last_changes: "last %{count} changes"
688 label_change_view_all: View all changes
689 label_change_view_all: View all changes
689 label_personalize_page: Personalize this page
690 label_personalize_page: Personalize this page
690 label_comment: Comment
691 label_comment: Comment
691 label_comment_plural: Comments
692 label_comment_plural: Comments
692 label_x_comments:
693 label_x_comments:
693 zero: no comments
694 zero: no comments
694 one: 1 comment
695 one: 1 comment
695 other: "%{count} comments"
696 other: "%{count} comments"
696 label_comment_add: Add a comment
697 label_comment_add: Add a comment
697 label_comment_added: Comment added
698 label_comment_added: Comment added
698 label_comment_delete: Delete comments
699 label_comment_delete: Delete comments
699 label_query: Custom query
700 label_query: Custom query
700 label_query_plural: Custom queries
701 label_query_plural: Custom queries
701 label_query_new: New query
702 label_query_new: New query
702 label_my_queries: My custom queries
703 label_my_queries: My custom queries
703 label_filter_add: Add filter
704 label_filter_add: Add filter
704 label_filter_plural: Filters
705 label_filter_plural: Filters
705 label_equals: is
706 label_equals: is
706 label_not_equals: is not
707 label_not_equals: is not
707 label_in_less_than: in less than
708 label_in_less_than: in less than
708 label_in_more_than: in more than
709 label_in_more_than: in more than
709 label_in_the_next_days: in the next
710 label_in_the_next_days: in the next
710 label_in_the_past_days: in the past
711 label_in_the_past_days: in the past
711 label_greater_or_equal: '>='
712 label_greater_or_equal: '>='
712 label_less_or_equal: '<='
713 label_less_or_equal: '<='
713 label_between: between
714 label_between: between
714 label_in: in
715 label_in: in
715 label_today: today
716 label_today: today
716 label_all_time: all time
717 label_all_time: all time
717 label_yesterday: yesterday
718 label_yesterday: yesterday
718 label_this_week: this week
719 label_this_week: this week
719 label_last_week: last week
720 label_last_week: last week
720 label_last_n_weeks: "last %{count} weeks"
721 label_last_n_weeks: "last %{count} weeks"
721 label_last_n_days: "last %{count} days"
722 label_last_n_days: "last %{count} days"
722 label_this_month: this month
723 label_this_month: this month
723 label_last_month: last month
724 label_last_month: last month
724 label_this_year: this year
725 label_this_year: this year
725 label_date_range: Date range
726 label_date_range: Date range
726 label_less_than_ago: less than days ago
727 label_less_than_ago: less than days ago
727 label_more_than_ago: more than days ago
728 label_more_than_ago: more than days ago
728 label_ago: days ago
729 label_ago: days ago
729 label_contains: contains
730 label_contains: contains
730 label_not_contains: doesn't contain
731 label_not_contains: doesn't contain
731 label_any_issues_in_project: any issues in project
732 label_any_issues_in_project: any issues in project
732 label_any_issues_not_in_project: any issues not in project
733 label_any_issues_not_in_project: any issues not in project
733 label_no_issues_in_project: no issues in project
734 label_no_issues_in_project: no issues in project
734 label_any_open_issues: any open issues
735 label_any_open_issues: any open issues
735 label_no_open_issues: no open issues
736 label_no_open_issues: no open issues
736 label_day_plural: days
737 label_day_plural: days
737 label_repository: Repository
738 label_repository: Repository
738 label_repository_new: New repository
739 label_repository_new: New repository
739 label_repository_plural: Repositories
740 label_repository_plural: Repositories
740 label_browse: Browse
741 label_browse: Browse
741 label_branch: Branch
742 label_branch: Branch
742 label_tag: Tag
743 label_tag: Tag
743 label_revision: Revision
744 label_revision: Revision
744 label_revision_plural: Revisions
745 label_revision_plural: Revisions
745 label_revision_id: "Revision %{value}"
746 label_revision_id: "Revision %{value}"
746 label_associated_revisions: Associated revisions
747 label_associated_revisions: Associated revisions
747 label_added: added
748 label_added: added
748 label_modified: modified
749 label_modified: modified
749 label_copied: copied
750 label_copied: copied
750 label_renamed: renamed
751 label_renamed: renamed
751 label_deleted: deleted
752 label_deleted: deleted
752 label_latest_revision: Latest revision
753 label_latest_revision: Latest revision
753 label_latest_revision_plural: Latest revisions
754 label_latest_revision_plural: Latest revisions
754 label_view_revisions: View revisions
755 label_view_revisions: View revisions
755 label_view_all_revisions: View all revisions
756 label_view_all_revisions: View all revisions
756 label_max_size: Maximum size
757 label_max_size: Maximum size
757 label_sort_highest: Move to top
758 label_sort_highest: Move to top
758 label_sort_higher: Move up
759 label_sort_higher: Move up
759 label_sort_lower: Move down
760 label_sort_lower: Move down
760 label_sort_lowest: Move to bottom
761 label_sort_lowest: Move to bottom
761 label_roadmap: Roadmap
762 label_roadmap: Roadmap
762 label_roadmap_due_in: "Due in %{value}"
763 label_roadmap_due_in: "Due in %{value}"
763 label_roadmap_overdue: "%{value} late"
764 label_roadmap_overdue: "%{value} late"
764 label_roadmap_no_issues: No issues for this version
765 label_roadmap_no_issues: No issues for this version
765 label_search: Search
766 label_search: Search
766 label_result_plural: Results
767 label_result_plural: Results
767 label_all_words: All words
768 label_all_words: All words
768 label_wiki: Wiki
769 label_wiki: Wiki
769 label_wiki_edit: Wiki edit
770 label_wiki_edit: Wiki edit
770 label_wiki_edit_plural: Wiki edits
771 label_wiki_edit_plural: Wiki edits
771 label_wiki_page: Wiki page
772 label_wiki_page: Wiki page
772 label_wiki_page_plural: Wiki pages
773 label_wiki_page_plural: Wiki pages
773 label_wiki_page_new: New wiki page
774 label_wiki_page_new: New wiki page
774 label_index_by_title: Index by title
775 label_index_by_title: Index by title
775 label_index_by_date: Index by date
776 label_index_by_date: Index by date
776 label_current_version: Current version
777 label_current_version: Current version
777 label_preview: Preview
778 label_preview: Preview
778 label_feed_plural: Feeds
779 label_feed_plural: Feeds
779 label_changes_details: Details of all changes
780 label_changes_details: Details of all changes
780 label_issue_tracking: Issue tracking
781 label_issue_tracking: Issue tracking
781 label_spent_time: Spent time
782 label_spent_time: Spent time
782 label_total_spent_time: Total spent time
783 label_total_spent_time: Total spent time
783 label_overall_spent_time: Overall spent time
784 label_overall_spent_time: Overall spent time
784 label_f_hour: "%{value} hour"
785 label_f_hour: "%{value} hour"
785 label_f_hour_plural: "%{value} hours"
786 label_f_hour_plural: "%{value} hours"
786 label_f_hour_short: "%{value} h"
787 label_f_hour_short: "%{value} h"
787 label_time_tracking: Time tracking
788 label_time_tracking: Time tracking
788 label_change_plural: Changes
789 label_change_plural: Changes
789 label_statistics: Statistics
790 label_statistics: Statistics
790 label_commits_per_month: Commits per month
791 label_commits_per_month: Commits per month
791 label_commits_per_author: Commits per author
792 label_commits_per_author: Commits per author
792 label_diff: diff
793 label_diff: diff
793 label_view_diff: View differences
794 label_view_diff: View differences
794 label_diff_inline: inline
795 label_diff_inline: inline
795 label_diff_side_by_side: side by side
796 label_diff_side_by_side: side by side
796 label_options: Options
797 label_options: Options
797 label_copy_workflow_from: Copy workflow from
798 label_copy_workflow_from: Copy workflow from
798 label_permissions_report: Permissions report
799 label_permissions_report: Permissions report
799 label_watched_issues: Watched issues
800 label_watched_issues: Watched issues
800 label_related_issues: Related issues
801 label_related_issues: Related issues
801 label_applied_status: Applied status
802 label_applied_status: Applied status
802 label_loading: Loading...
803 label_loading: Loading...
803 label_relation_new: New relation
804 label_relation_new: New relation
804 label_relation_delete: Delete relation
805 label_relation_delete: Delete relation
805 label_relates_to: Related to
806 label_relates_to: Related to
806 label_duplicates: Duplicates
807 label_duplicates: Duplicates
807 label_duplicated_by: Duplicated by
808 label_duplicated_by: Duplicated by
808 label_blocks: Blocks
809 label_blocks: Blocks
809 label_blocked_by: Blocked by
810 label_blocked_by: Blocked by
810 label_precedes: Precedes
811 label_precedes: Precedes
811 label_follows: Follows
812 label_follows: Follows
812 label_copied_to: Copied to
813 label_copied_to: Copied to
813 label_copied_from: Copied from
814 label_copied_from: Copied from
814 label_stay_logged_in: Stay logged in
815 label_stay_logged_in: Stay logged in
815 label_disabled: disabled
816 label_disabled: disabled
816 label_show_completed_versions: Show completed versions
817 label_show_completed_versions: Show completed versions
817 label_me: me
818 label_me: me
818 label_board: Forum
819 label_board: Forum
819 label_board_new: New forum
820 label_board_new: New forum
820 label_board_plural: Forums
821 label_board_plural: Forums
821 label_board_locked: Locked
822 label_board_locked: Locked
822 label_board_sticky: Sticky
823 label_board_sticky: Sticky
823 label_topic_plural: Topics
824 label_topic_plural: Topics
824 label_message_plural: Messages
825 label_message_plural: Messages
825 label_message_last: Last message
826 label_message_last: Last message
826 label_message_new: New message
827 label_message_new: New message
827 label_message_posted: Message added
828 label_message_posted: Message added
828 label_reply_plural: Replies
829 label_reply_plural: Replies
829 label_send_information: Send account information to the user
830 label_send_information: Send account information to the user
830 label_year: Year
831 label_year: Year
831 label_month: Month
832 label_month: Month
832 label_week: Week
833 label_week: Week
833 label_date_from: From
834 label_date_from: From
834 label_date_to: To
835 label_date_to: To
835 label_language_based: Based on user's language
836 label_language_based: Based on user's language
836 label_sort_by: "Sort by %{value}"
837 label_sort_by: "Sort by %{value}"
837 label_send_test_email: Send a test email
838 label_send_test_email: Send a test email
838 label_feeds_access_key: Atom access key
839 label_feeds_access_key: Atom access key
839 label_missing_feeds_access_key: Missing a Atom access key
840 label_missing_feeds_access_key: Missing a Atom access key
840 label_feeds_access_key_created_on: "Atom access key created %{value} ago"
841 label_feeds_access_key_created_on: "Atom access key created %{value} ago"
841 label_module_plural: Modules
842 label_module_plural: Modules
842 label_added_time_by: "Added by %{author} %{age} ago"
843 label_added_time_by: "Added by %{author} %{age} ago"
843 label_updated_time_by: "Updated by %{author} %{age} ago"
844 label_updated_time_by: "Updated by %{author} %{age} ago"
844 label_updated_time: "Updated %{value} ago"
845 label_updated_time: "Updated %{value} ago"
845 label_jump_to_a_project: Jump to a project...
846 label_jump_to_a_project: Jump to a project...
846 label_file_plural: Files
847 label_file_plural: Files
847 label_changeset_plural: Changesets
848 label_changeset_plural: Changesets
848 label_default_columns: Default columns
849 label_default_columns: Default columns
849 label_no_change_option: (No change)
850 label_no_change_option: (No change)
850 label_bulk_edit_selected_issues: Bulk edit selected issues
851 label_bulk_edit_selected_issues: Bulk edit selected issues
851 label_bulk_edit_selected_time_entries: Bulk edit selected time entries
852 label_bulk_edit_selected_time_entries: Bulk edit selected time entries
852 label_theme: Theme
853 label_theme: Theme
853 label_default: Default
854 label_default: Default
854 label_search_titles_only: Search titles only
855 label_search_titles_only: Search titles only
855 label_user_mail_option_all: "For any event on all my projects"
856 label_user_mail_option_all: "For any event on all my projects"
856 label_user_mail_option_selected: "For any event on the selected projects only..."
857 label_user_mail_option_selected: "For any event on the selected projects only..."
857 label_user_mail_option_none: "No events"
858 label_user_mail_option_none: "No events"
858 label_user_mail_option_only_my_events: "Only for things I watch or I'm involved in"
859 label_user_mail_option_only_my_events: "Only for things I watch or I'm involved in"
859 label_user_mail_option_only_assigned: "Only for things I am assigned to"
860 label_user_mail_option_only_assigned: "Only for things I am assigned to"
860 label_user_mail_option_only_owner: "Only for things I am the owner of"
861 label_user_mail_option_only_owner: "Only for things I am the owner of"
861 label_user_mail_no_self_notified: "I don't want to be notified of changes that I make myself"
862 label_user_mail_no_self_notified: "I don't want to be notified of changes that I make myself"
862 label_registration_activation_by_email: account activation by email
863 label_registration_activation_by_email: account activation by email
863 label_registration_manual_activation: manual account activation
864 label_registration_manual_activation: manual account activation
864 label_registration_automatic_activation: automatic account activation
865 label_registration_automatic_activation: automatic account activation
865 label_display_per_page: "Per page: %{value}"
866 label_display_per_page: "Per page: %{value}"
866 label_age: Age
867 label_age: Age
867 label_change_properties: Change properties
868 label_change_properties: Change properties
868 label_general: General
869 label_general: General
869 label_more: More
870 label_more: More
870 label_scm: SCM
871 label_scm: SCM
871 label_plugins: Plugins
872 label_plugins: Plugins
872 label_ldap_authentication: LDAP authentication
873 label_ldap_authentication: LDAP authentication
873 label_downloads_abbr: D/L
874 label_downloads_abbr: D/L
874 label_optional_description: Optional description
875 label_optional_description: Optional description
875 label_add_another_file: Add another file
876 label_add_another_file: Add another file
876 label_preferences: Preferences
877 label_preferences: Preferences
877 label_chronological_order: In chronological order
878 label_chronological_order: In chronological order
878 label_reverse_chronological_order: In reverse chronological order
879 label_reverse_chronological_order: In reverse chronological order
879 label_planning: Planning
880 label_planning: Planning
880 label_incoming_emails: Incoming emails
881 label_incoming_emails: Incoming emails
881 label_generate_key: Generate a key
882 label_generate_key: Generate a key
882 label_issue_watchers: Watchers
883 label_issue_watchers: Watchers
883 label_example: Example
884 label_example: Example
884 label_display: Display
885 label_display: Display
885 label_sort: Sort
886 label_sort: Sort
886 label_ascending: Ascending
887 label_ascending: Ascending
887 label_descending: Descending
888 label_descending: Descending
888 label_date_from_to: From %{start} to %{end}
889 label_date_from_to: From %{start} to %{end}
889 label_wiki_content_added: Wiki page added
890 label_wiki_content_added: Wiki page added
890 label_wiki_content_updated: Wiki page updated
891 label_wiki_content_updated: Wiki page updated
891 label_group: Group
892 label_group: Group
892 label_group_plural: Groups
893 label_group_plural: Groups
893 label_group_new: New group
894 label_group_new: New group
894 label_group_anonymous: Anonymous users
895 label_group_anonymous: Anonymous users
895 label_group_non_member: Non member users
896 label_group_non_member: Non member users
896 label_time_entry_plural: Spent time
897 label_time_entry_plural: Spent time
897 label_version_sharing_none: Not shared
898 label_version_sharing_none: Not shared
898 label_version_sharing_descendants: With subprojects
899 label_version_sharing_descendants: With subprojects
899 label_version_sharing_hierarchy: With project hierarchy
900 label_version_sharing_hierarchy: With project hierarchy
900 label_version_sharing_tree: With project tree
901 label_version_sharing_tree: With project tree
901 label_version_sharing_system: With all projects
902 label_version_sharing_system: With all projects
902 label_update_issue_done_ratios: Update issue done ratios
903 label_update_issue_done_ratios: Update issue done ratios
903 label_copy_source: Source
904 label_copy_source: Source
904 label_copy_target: Target
905 label_copy_target: Target
905 label_copy_same_as_target: Same as target
906 label_copy_same_as_target: Same as target
906 label_display_used_statuses_only: Only display statuses that are used by this tracker
907 label_display_used_statuses_only: Only display statuses that are used by this tracker
907 label_api_access_key: API access key
908 label_api_access_key: API access key
908 label_missing_api_access_key: Missing an API access key
909 label_missing_api_access_key: Missing an API access key
909 label_api_access_key_created_on: "API access key created %{value} ago"
910 label_api_access_key_created_on: "API access key created %{value} ago"
910 label_profile: Profile
911 label_profile: Profile
911 label_subtask_plural: Subtasks
912 label_subtask_plural: Subtasks
912 label_project_copy_notifications: Send email notifications during the project copy
913 label_project_copy_notifications: Send email notifications during the project copy
913 label_principal_search: "Search for user or group:"
914 label_principal_search: "Search for user or group:"
914 label_user_search: "Search for user:"
915 label_user_search: "Search for user:"
915 label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author
916 label_additional_workflow_transitions_for_author: Additional transitions allowed when the user is the author
916 label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee
917 label_additional_workflow_transitions_for_assignee: Additional transitions allowed when the user is the assignee
917 label_issues_visibility_all: All issues
918 label_issues_visibility_all: All issues
918 label_issues_visibility_public: All non private issues
919 label_issues_visibility_public: All non private issues
919 label_issues_visibility_own: Issues created by or assigned to the user
920 label_issues_visibility_own: Issues created by or assigned to the user
920 label_git_report_last_commit: Report last commit for files and directories
921 label_git_report_last_commit: Report last commit for files and directories
921 label_parent_revision: Parent
922 label_parent_revision: Parent
922 label_child_revision: Child
923 label_child_revision: Child
923 label_export_options: "%{export_format} export options"
924 label_export_options: "%{export_format} export options"
924 label_copy_attachments: Copy attachments
925 label_copy_attachments: Copy attachments
925 label_copy_subtasks: Copy subtasks
926 label_copy_subtasks: Copy subtasks
926 label_item_position: "%{position} of %{count}"
927 label_item_position: "%{position} of %{count}"
927 label_completed_versions: Completed versions
928 label_completed_versions: Completed versions
928 label_search_for_watchers: Search for watchers to add
929 label_search_for_watchers: Search for watchers to add
929 label_session_expiration: Session expiration
930 label_session_expiration: Session expiration
930 label_show_closed_projects: View closed projects
931 label_show_closed_projects: View closed projects
931 label_status_transitions: Status transitions
932 label_status_transitions: Status transitions
932 label_fields_permissions: Fields permissions
933 label_fields_permissions: Fields permissions
933 label_readonly: Read-only
934 label_readonly: Read-only
934 label_required: Required
935 label_required: Required
935 label_hidden: Hidden
936 label_hidden: Hidden
936 label_attribute_of_project: "Project's %{name}"
937 label_attribute_of_project: "Project's %{name}"
937 label_attribute_of_issue: "Issue's %{name}"
938 label_attribute_of_issue: "Issue's %{name}"
938 label_attribute_of_author: "Author's %{name}"
939 label_attribute_of_author: "Author's %{name}"
939 label_attribute_of_assigned_to: "Assignee's %{name}"
940 label_attribute_of_assigned_to: "Assignee's %{name}"
940 label_attribute_of_user: "User's %{name}"
941 label_attribute_of_user: "User's %{name}"
941 label_attribute_of_fixed_version: "Target version's %{name}"
942 label_attribute_of_fixed_version: "Target version's %{name}"
942 label_cross_project_descendants: With subprojects
943 label_cross_project_descendants: With subprojects
943 label_cross_project_tree: With project tree
944 label_cross_project_tree: With project tree
944 label_cross_project_hierarchy: With project hierarchy
945 label_cross_project_hierarchy: With project hierarchy
945 label_cross_project_system: With all projects
946 label_cross_project_system: With all projects
946 label_gantt_progress_line: Progress line
947 label_gantt_progress_line: Progress line
947 label_visibility_private: to me only
948 label_visibility_private: to me only
948 label_visibility_roles: to these roles only
949 label_visibility_roles: to these roles only
949 label_visibility_public: to any users
950 label_visibility_public: to any users
950 label_link: Link
951 label_link: Link
951 label_only: only
952 label_only: only
952 label_drop_down_list: drop-down list
953 label_drop_down_list: drop-down list
953 label_checkboxes: checkboxes
954 label_checkboxes: checkboxes
954 label_radio_buttons: radio buttons
955 label_radio_buttons: radio buttons
955 label_link_values_to: Link values to URL
956 label_link_values_to: Link values to URL
956 label_custom_field_select_type: Select the type of object to which the custom field is to be attached
957 label_custom_field_select_type: Select the type of object to which the custom field is to be attached
957 label_check_for_updates: Check for updates
958 label_check_for_updates: Check for updates
958 label_latest_compatible_version: Latest compatible version
959 label_latest_compatible_version: Latest compatible version
959 label_unknown_plugin: Unknown plugin
960 label_unknown_plugin: Unknown plugin
960 label_add_projects: Add projects
961 label_add_projects: Add projects
961 label_users_visibility_all: All active users
962 label_users_visibility_all: All active users
962 label_users_visibility_members_of_visible_projects: Members of visible projects
963 label_users_visibility_members_of_visible_projects: Members of visible projects
963 label_edit_attachments: Edit attached files
964 label_edit_attachments: Edit attached files
964 label_link_copied_issue: Link copied issue
965 label_link_copied_issue: Link copied issue
965 label_ask: Ask
966 label_ask: Ask
966 label_search_attachments_yes: Search attachment filenames and descriptions
967 label_search_attachments_yes: Search attachment filenames and descriptions
967 label_search_attachments_no: Do not search attachments
968 label_search_attachments_no: Do not search attachments
968 label_search_attachments_only: Search attachments only
969 label_search_attachments_only: Search attachments only
969 label_search_open_issues_only: Open issues only
970 label_search_open_issues_only: Open issues only
970 label_email_address_plural: Emails
971 label_email_address_plural: Emails
971 label_email_address_add: Add email address
972 label_email_address_add: Add email address
972 label_enable_notifications: Enable notifications
973 label_enable_notifications: Enable notifications
973 label_disable_notifications: Disable notifications
974 label_disable_notifications: Disable notifications
974 label_blank_value: blank
975 label_blank_value: blank
975 label_parent_task_attributes: Parent tasks attributes
976 label_parent_task_attributes: Parent tasks attributes
976 label_parent_task_attributes_derived: Calculated from subtasks
977 label_parent_task_attributes_derived: Calculated from subtasks
977 label_parent_task_attributes_independent: Independent of subtasks
978 label_parent_task_attributes_independent: Independent of subtasks
978 label_time_entries_visibility_all: All time entries
979 label_time_entries_visibility_all: All time entries
979 label_time_entries_visibility_own: Time entries created by the user
980 label_time_entries_visibility_own: Time entries created by the user
980 label_member_management: Member management
981 label_member_management: Member management
981 label_member_management_all_roles: All roles
982 label_member_management_all_roles: All roles
982 label_member_management_selected_roles_only: Only these roles
983 label_member_management_selected_roles_only: Only these roles
983 label_import_issues: Import issues
984 label_import_issues: Import issues
984 label_select_file_to_import: Select the file to import
985 label_select_file_to_import: Select the file to import
985 label_fields_separator: Field separator
986 label_fields_separator: Field separator
986 label_fields_wrapper: Field wrapper
987 label_fields_wrapper: Field wrapper
987 label_encoding: Encoding
988 label_encoding: Encoding
988 label_comma_char: Comma
989 label_comma_char: Comma
989 label_semi_colon_char: Semicolon
990 label_semi_colon_char: Semicolon
990 label_quote_char: Quote
991 label_quote_char: Quote
991 label_double_quote_char: Double quote
992 label_double_quote_char: Double quote
992 label_fields_mapping: Fields mapping
993 label_fields_mapping: Fields mapping
993 label_file_content_preview: File content preview
994 label_file_content_preview: File content preview
994 label_create_missing_values: Create missing values
995 label_create_missing_values: Create missing values
995 label_api: API
996 label_api: API
996 label_field_format_enumeration: Key/value list
997 label_field_format_enumeration: Key/value list
997 label_default_values_for_new_users: Default values for new users
998 label_default_values_for_new_users: Default values for new users
998 label_relations: Relations
999 label_relations: Relations
999 label_new_project_issue_tab_enabled: Display the "New issue" tab
1000 label_new_project_issue_tab_enabled: Display the "New issue" tab
1000 label_new_object_tab_enabled: Display the "+" drop-down
1001 label_new_object_tab_enabled: Display the "+" drop-down
1002 label_font_default: Default font
1003 label_font_monospace: Monospaced font
1004 label_font_proportional: Proportional font
1001
1005
1002 button_login: Login
1006 button_login: Login
1003 button_submit: Submit
1007 button_submit: Submit
1004 button_save: Save
1008 button_save: Save
1005 button_check_all: Check all
1009 button_check_all: Check all
1006 button_uncheck_all: Uncheck all
1010 button_uncheck_all: Uncheck all
1007 button_collapse_all: Collapse all
1011 button_collapse_all: Collapse all
1008 button_expand_all: Expand all
1012 button_expand_all: Expand all
1009 button_delete: Delete
1013 button_delete: Delete
1010 button_create: Create
1014 button_create: Create
1011 button_create_and_continue: Create and continue
1015 button_create_and_continue: Create and continue
1012 button_test: Test
1016 button_test: Test
1013 button_edit: Edit
1017 button_edit: Edit
1014 button_edit_associated_wikipage: "Edit associated Wiki page: %{page_title}"
1018 button_edit_associated_wikipage: "Edit associated Wiki page: %{page_title}"
1015 button_add: Add
1019 button_add: Add
1016 button_change: Change
1020 button_change: Change
1017 button_apply: Apply
1021 button_apply: Apply
1018 button_clear: Clear
1022 button_clear: Clear
1019 button_lock: Lock
1023 button_lock: Lock
1020 button_unlock: Unlock
1024 button_unlock: Unlock
1021 button_download: Download
1025 button_download: Download
1022 button_list: List
1026 button_list: List
1023 button_view: View
1027 button_view: View
1024 button_move: Move
1028 button_move: Move
1025 button_move_and_follow: Move and follow
1029 button_move_and_follow: Move and follow
1026 button_back: Back
1030 button_back: Back
1027 button_cancel: Cancel
1031 button_cancel: Cancel
1028 button_activate: Activate
1032 button_activate: Activate
1029 button_sort: Sort
1033 button_sort: Sort
1030 button_log_time: Log time
1034 button_log_time: Log time
1031 button_rollback: Rollback to this version
1035 button_rollback: Rollback to this version
1032 button_watch: Watch
1036 button_watch: Watch
1033 button_unwatch: Unwatch
1037 button_unwatch: Unwatch
1034 button_reply: Reply
1038 button_reply: Reply
1035 button_archive: Archive
1039 button_archive: Archive
1036 button_unarchive: Unarchive
1040 button_unarchive: Unarchive
1037 button_reset: Reset
1041 button_reset: Reset
1038 button_rename: Rename
1042 button_rename: Rename
1039 button_change_password: Change password
1043 button_change_password: Change password
1040 button_copy: Copy
1044 button_copy: Copy
1041 button_copy_and_follow: Copy and follow
1045 button_copy_and_follow: Copy and follow
1042 button_annotate: Annotate
1046 button_annotate: Annotate
1043 button_update: Update
1047 button_update: Update
1044 button_configure: Configure
1048 button_configure: Configure
1045 button_quote: Quote
1049 button_quote: Quote
1046 button_duplicate: Duplicate
1050 button_duplicate: Duplicate
1047 button_show: Show
1051 button_show: Show
1048 button_hide: Hide
1052 button_hide: Hide
1049 button_edit_section: Edit this section
1053 button_edit_section: Edit this section
1050 button_export: Export
1054 button_export: Export
1051 button_delete_my_account: Delete my account
1055 button_delete_my_account: Delete my account
1052 button_close: Close
1056 button_close: Close
1053 button_reopen: Reopen
1057 button_reopen: Reopen
1054 button_import: Import
1058 button_import: Import
1055 button_filter: Filter
1059 button_filter: Filter
1056
1060
1057 status_active: active
1061 status_active: active
1058 status_registered: registered
1062 status_registered: registered
1059 status_locked: locked
1063 status_locked: locked
1060
1064
1061 project_status_active: active
1065 project_status_active: active
1062 project_status_closed: closed
1066 project_status_closed: closed
1063 project_status_archived: archived
1067 project_status_archived: archived
1064
1068
1065 version_status_open: open
1069 version_status_open: open
1066 version_status_locked: locked
1070 version_status_locked: locked
1067 version_status_closed: closed
1071 version_status_closed: closed
1068
1072
1069 field_active: Active
1073 field_active: Active
1070
1074
1071 text_select_mail_notifications: Select actions for which email notifications should be sent.
1075 text_select_mail_notifications: Select actions for which email notifications should be sent.
1072 text_regexp_info: eg. ^[A-Z0-9]+$
1076 text_regexp_info: eg. ^[A-Z0-9]+$
1073 text_min_max_length_info: 0 means no restriction
1077 text_min_max_length_info: 0 means no restriction
1074 text_project_destroy_confirmation: Are you sure you want to delete this project and related data?
1078 text_project_destroy_confirmation: Are you sure you want to delete this project and related data?
1075 text_subprojects_destroy_warning: "Its subproject(s): %{value} will be also deleted."
1079 text_subprojects_destroy_warning: "Its subproject(s): %{value} will be also deleted."
1076 text_workflow_edit: Select a role and a tracker to edit the workflow
1080 text_workflow_edit: Select a role and a tracker to edit the workflow
1077 text_are_you_sure: Are you sure?
1081 text_are_you_sure: Are you sure?
1078 text_journal_changed: "%{label} changed from %{old} to %{new}"
1082 text_journal_changed: "%{label} changed from %{old} to %{new}"
1079 text_journal_changed_no_detail: "%{label} updated"
1083 text_journal_changed_no_detail: "%{label} updated"
1080 text_journal_set_to: "%{label} set to %{value}"
1084 text_journal_set_to: "%{label} set to %{value}"
1081 text_journal_deleted: "%{label} deleted (%{old})"
1085 text_journal_deleted: "%{label} deleted (%{old})"
1082 text_journal_added: "%{label} %{value} added"
1086 text_journal_added: "%{label} %{value} added"
1083 text_tip_issue_begin_day: issue beginning this day
1087 text_tip_issue_begin_day: issue beginning this day
1084 text_tip_issue_end_day: issue ending this day
1088 text_tip_issue_end_day: issue ending this day
1085 text_tip_issue_begin_end_day: issue beginning and ending this day
1089 text_tip_issue_begin_end_day: issue beginning and ending this day
1086 text_project_identifier_info: 'Only lower case letters (a-z), numbers, dashes and underscores are allowed, must start with a lower case letter.<br />Once saved, the identifier cannot be changed.'
1090 text_project_identifier_info: 'Only lower case letters (a-z), numbers, dashes and underscores are allowed, must start with a lower case letter.<br />Once saved, the identifier cannot be changed.'
1087 text_caracters_maximum: "%{count} characters maximum."
1091 text_caracters_maximum: "%{count} characters maximum."
1088 text_caracters_minimum: "Must be at least %{count} characters long."
1092 text_caracters_minimum: "Must be at least %{count} characters long."
1089 text_length_between: "Length between %{min} and %{max} characters."
1093 text_length_between: "Length between %{min} and %{max} characters."
1090 text_tracker_no_workflow: No workflow defined for this tracker
1094 text_tracker_no_workflow: No workflow defined for this tracker
1091 text_unallowed_characters: Unallowed characters
1095 text_unallowed_characters: Unallowed characters
1092 text_comma_separated: Multiple values allowed (comma separated).
1096 text_comma_separated: Multiple values allowed (comma separated).
1093 text_line_separated: Multiple values allowed (one line for each value).
1097 text_line_separated: Multiple values allowed (one line for each value).
1094 text_issues_ref_in_commit_messages: Referencing and fixing issues in commit messages
1098 text_issues_ref_in_commit_messages: Referencing and fixing issues in commit messages
1095 text_issue_added: "Issue %{id} has been reported by %{author}."
1099 text_issue_added: "Issue %{id} has been reported by %{author}."
1096 text_issue_updated: "Issue %{id} has been updated by %{author}."
1100 text_issue_updated: "Issue %{id} has been updated by %{author}."
1097 text_wiki_destroy_confirmation: Are you sure you want to delete this wiki and all its content?
1101 text_wiki_destroy_confirmation: Are you sure you want to delete this wiki and all its content?
1098 text_issue_category_destroy_question: "Some issues (%{count}) are assigned to this category. What do you want to do?"
1102 text_issue_category_destroy_question: "Some issues (%{count}) are assigned to this category. What do you want to do?"
1099 text_issue_category_destroy_assignments: Remove category assignments
1103 text_issue_category_destroy_assignments: Remove category assignments
1100 text_issue_category_reassign_to: Reassign issues to this category
1104 text_issue_category_reassign_to: Reassign issues to this category
1101 text_user_mail_option: "For unselected projects, you will only receive notifications about things you watch or you're involved in (eg. issues you're the author or assignee)."
1105 text_user_mail_option: "For unselected projects, you will only receive notifications about things you watch or you're involved in (eg. issues you're the author or assignee)."
1102 text_no_configuration_data: "Roles, trackers, issue statuses and workflow have not been configured yet.\nIt is highly recommended to load the default configuration. You will be able to modify it once loaded."
1106 text_no_configuration_data: "Roles, trackers, issue statuses and workflow have not been configured yet.\nIt is highly recommended to load the default configuration. You will be able to modify it once loaded."
1103 text_load_default_configuration: Load the default configuration
1107 text_load_default_configuration: Load the default configuration
1104 text_status_changed_by_changeset: "Applied in changeset %{value}."
1108 text_status_changed_by_changeset: "Applied in changeset %{value}."
1105 text_time_logged_by_changeset: "Applied in changeset %{value}."
1109 text_time_logged_by_changeset: "Applied in changeset %{value}."
1106 text_issues_destroy_confirmation: 'Are you sure you want to delete the selected issue(s)?'
1110 text_issues_destroy_confirmation: 'Are you sure you want to delete the selected issue(s)?'
1107 text_issues_destroy_descendants_confirmation: "This will also delete %{count} subtask(s)."
1111 text_issues_destroy_descendants_confirmation: "This will also delete %{count} subtask(s)."
1108 text_time_entries_destroy_confirmation: 'Are you sure you want to delete the selected time entr(y/ies)?'
1112 text_time_entries_destroy_confirmation: 'Are you sure you want to delete the selected time entr(y/ies)?'
1109 text_select_project_modules: 'Select modules to enable for this project:'
1113 text_select_project_modules: 'Select modules to enable for this project:'
1110 text_default_administrator_account_changed: Default administrator account changed
1114 text_default_administrator_account_changed: Default administrator account changed
1111 text_file_repository_writable: Attachments directory writable
1115 text_file_repository_writable: Attachments directory writable
1112 text_plugin_assets_writable: Plugin assets directory writable
1116 text_plugin_assets_writable: Plugin assets directory writable
1113 text_rmagick_available: RMagick available (optional)
1117 text_rmagick_available: RMagick available (optional)
1114 text_convert_available: ImageMagick convert available (optional)
1118 text_convert_available: ImageMagick convert available (optional)
1115 text_destroy_time_entries_question: "%{hours} hours were reported on the issues you are about to delete. What do you want to do?"
1119 text_destroy_time_entries_question: "%{hours} hours were reported on the issues you are about to delete. What do you want to do?"
1116 text_destroy_time_entries: Delete reported hours
1120 text_destroy_time_entries: Delete reported hours
1117 text_assign_time_entries_to_project: Assign reported hours to the project
1121 text_assign_time_entries_to_project: Assign reported hours to the project
1118 text_reassign_time_entries: 'Reassign reported hours to this issue:'
1122 text_reassign_time_entries: 'Reassign reported hours to this issue:'
1119 text_user_wrote: "%{value} wrote:"
1123 text_user_wrote: "%{value} wrote:"
1120 text_enumeration_destroy_question: "%{count} objects are assigned to the value β€œ%{name}”."
1124 text_enumeration_destroy_question: "%{count} objects are assigned to the value β€œ%{name}”."
1121 text_enumeration_category_reassign_to: 'Reassign them to this value:'
1125 text_enumeration_category_reassign_to: 'Reassign them to this value:'
1122 text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/configuration.yml and restart the application to enable them."
1126 text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/configuration.yml and restart the application to enable them."
1123 text_repository_usernames_mapping: "Select or update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped."
1127 text_repository_usernames_mapping: "Select or update the Redmine user mapped to each username found in the repository log.\nUsers with the same Redmine and repository username or email are automatically mapped."
1124 text_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.'
1128 text_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.'
1125 text_custom_field_possible_values_info: 'One line for each value'
1129 text_custom_field_possible_values_info: 'One line for each value'
1126 text_wiki_page_destroy_question: "This page has %{descendants} child page(s) and descendant(s). What do you want to do?"
1130 text_wiki_page_destroy_question: "This page has %{descendants} child page(s) and descendant(s). What do you want to do?"
1127 text_wiki_page_nullify_children: "Keep child pages as root pages"
1131 text_wiki_page_nullify_children: "Keep child pages as root pages"
1128 text_wiki_page_destroy_children: "Delete child pages and all their descendants"
1132 text_wiki_page_destroy_children: "Delete child pages and all their descendants"
1129 text_wiki_page_reassign_children: "Reassign child pages to this parent page"
1133 text_wiki_page_reassign_children: "Reassign child pages to this parent page"
1130 text_own_membership_delete_confirmation: "You are about to remove some or all of your permissions and may no longer be able to edit this project after that.\nAre you sure you want to continue?"
1134 text_own_membership_delete_confirmation: "You are about to remove some or all of your permissions and may no longer be able to edit this project after that.\nAre you sure you want to continue?"
1131 text_zoom_in: Zoom in
1135 text_zoom_in: Zoom in
1132 text_zoom_out: Zoom out
1136 text_zoom_out: Zoom out
1133 text_warn_on_leaving_unsaved: "The current page contains unsaved text that will be lost if you leave this page."
1137 text_warn_on_leaving_unsaved: "The current page contains unsaved text that will be lost if you leave this page."
1134 text_scm_path_encoding_note: "Default: UTF-8"
1138 text_scm_path_encoding_note: "Default: UTF-8"
1135 text_subversion_repository_note: "Examples: file:///, http://, https://, svn://, svn+[tunnelscheme]://"
1139 text_subversion_repository_note: "Examples: file:///, http://, https://, svn://, svn+[tunnelscheme]://"
1136 text_git_repository_note: Repository is bare and local (e.g. /gitrepo, c:\gitrepo)
1140 text_git_repository_note: Repository is bare and local (e.g. /gitrepo, c:\gitrepo)
1137 text_mercurial_repository_note: Local repository (e.g. /hgrepo, c:\hgrepo)
1141 text_mercurial_repository_note: Local repository (e.g. /hgrepo, c:\hgrepo)
1138 text_scm_command: Command
1142 text_scm_command: Command
1139 text_scm_command_version: Version
1143 text_scm_command_version: Version
1140 text_scm_config: You can configure your SCM commands in config/configuration.yml. Please restart the application after editing it.
1144 text_scm_config: You can configure your SCM commands in config/configuration.yml. Please restart the application after editing it.
1141 text_scm_command_not_available: SCM command is not available. Please check settings on the administration panel.
1145 text_scm_command_not_available: SCM command is not available. Please check settings on the administration panel.
1142 text_issue_conflict_resolution_overwrite: "Apply my changes anyway (previous notes will be kept but some changes may be overwritten)"
1146 text_issue_conflict_resolution_overwrite: "Apply my changes anyway (previous notes will be kept but some changes may be overwritten)"
1143 text_issue_conflict_resolution_add_notes: "Add my notes and discard my other changes"
1147 text_issue_conflict_resolution_add_notes: "Add my notes and discard my other changes"
1144 text_issue_conflict_resolution_cancel: "Discard all my changes and redisplay %{link}"
1148 text_issue_conflict_resolution_cancel: "Discard all my changes and redisplay %{link}"
1145 text_account_destroy_confirmation: "Are you sure you want to proceed?\nYour account will be permanently deleted, with no way to reactivate it."
1149 text_account_destroy_confirmation: "Are you sure you want to proceed?\nYour account will be permanently deleted, with no way to reactivate it."
1146 text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours."
1150 text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours."
1147 text_project_closed: This project is closed and read-only.
1151 text_project_closed: This project is closed and read-only.
1148 text_turning_multiple_off: "If you disable multiple values, multiple values will be removed in order to preserve only one value per item."
1152 text_turning_multiple_off: "If you disable multiple values, multiple values will be removed in order to preserve only one value per item."
1149
1153
1150 default_role_manager: Manager
1154 default_role_manager: Manager
1151 default_role_developer: Developer
1155 default_role_developer: Developer
1152 default_role_reporter: Reporter
1156 default_role_reporter: Reporter
1153 default_tracker_bug: Bug
1157 default_tracker_bug: Bug
1154 default_tracker_feature: Feature
1158 default_tracker_feature: Feature
1155 default_tracker_support: Support
1159 default_tracker_support: Support
1156 default_issue_status_new: New
1160 default_issue_status_new: New
1157 default_issue_status_in_progress: In Progress
1161 default_issue_status_in_progress: In Progress
1158 default_issue_status_resolved: Resolved
1162 default_issue_status_resolved: Resolved
1159 default_issue_status_feedback: Feedback
1163 default_issue_status_feedback: Feedback
1160 default_issue_status_closed: Closed
1164 default_issue_status_closed: Closed
1161 default_issue_status_rejected: Rejected
1165 default_issue_status_rejected: Rejected
1162 default_doc_category_user: User documentation
1166 default_doc_category_user: User documentation
1163 default_doc_category_tech: Technical documentation
1167 default_doc_category_tech: Technical documentation
1164 default_priority_low: Low
1168 default_priority_low: Low
1165 default_priority_normal: Normal
1169 default_priority_normal: Normal
1166 default_priority_high: High
1170 default_priority_high: High
1167 default_priority_urgent: Urgent
1171 default_priority_urgent: Urgent
1168 default_priority_immediate: Immediate
1172 default_priority_immediate: Immediate
1169 default_activity_design: Design
1173 default_activity_design: Design
1170 default_activity_development: Development
1174 default_activity_development: Development
1171
1175
1172 enumeration_issue_priorities: Issue priorities
1176 enumeration_issue_priorities: Issue priorities
1173 enumeration_doc_categories: Document categories
1177 enumeration_doc_categories: Document categories
1174 enumeration_activities: Activities (time tracking)
1178 enumeration_activities: Activities (time tracking)
1175 enumeration_system_activity: System Activity
1179 enumeration_system_activity: System Activity
1176 description_filter: Filter
1180 description_filter: Filter
1177 description_search: Searchfield
1181 description_search: Searchfield
1178 description_choose_project: Projects
1182 description_choose_project: Projects
1179 description_project_scope: Search scope
1183 description_project_scope: Search scope
1180 description_notes: Notes
1184 description_notes: Notes
1181 description_message_content: Message content
1185 description_message_content: Message content
1182 description_query_sort_criteria_attribute: Sort attribute
1186 description_query_sort_criteria_attribute: Sort attribute
1183 description_query_sort_criteria_direction: Sort direction
1187 description_query_sort_criteria_direction: Sort direction
1184 description_user_mail_notification: Mail notification settings
1188 description_user_mail_notification: Mail notification settings
1185 description_available_columns: Available Columns
1189 description_available_columns: Available Columns
1186 description_selected_columns: Selected Columns
1190 description_selected_columns: Selected Columns
1187 description_all_columns: All Columns
1191 description_all_columns: All Columns
1188 description_issue_category_reassign: Choose issue category
1192 description_issue_category_reassign: Choose issue category
1189 description_wiki_subpages_reassign: Choose new parent page
1193 description_wiki_subpages_reassign: Choose new parent page
1190 description_date_range_list: Choose range from list
1194 description_date_range_list: Choose range from list
1191 description_date_range_interval: Choose range by selecting start and end date
1195 description_date_range_interval: Choose range by selecting start and end date
1192 description_date_from: Enter start date
1196 description_date_from: Enter start date
1193 description_date_to: Enter end date
1197 description_date_to: Enter end date
1194 text_repository_identifier_info: 'Only lower case letters (a-z), numbers, dashes and underscores are allowed.<br />Once saved, the identifier cannot be changed.'
1198 text_repository_identifier_info: 'Only lower case letters (a-z), numbers, dashes and underscores are allowed.<br />Once saved, the identifier cannot be changed.'
@@ -1,1214 +1,1218
1 # French translations for Ruby on Rails
1 # French translations for Ruby on Rails
2 # by Christian Lescuyer (christian@flyingcoders.com)
2 # by Christian Lescuyer (christian@flyingcoders.com)
3 # contributor: Sebastien Grosjean - ZenCocoon.com
3 # contributor: Sebastien Grosjean - ZenCocoon.com
4 # contributor: Thibaut Cuvelier - Developpez.com
4 # contributor: Thibaut Cuvelier - Developpez.com
5
5
6 fr:
6 fr:
7 direction: ltr
7 direction: ltr
8 date:
8 date:
9 formats:
9 formats:
10 default: "%d/%m/%Y"
10 default: "%d/%m/%Y"
11 short: "%e %b"
11 short: "%e %b"
12 long: "%e %B %Y"
12 long: "%e %B %Y"
13 long_ordinal: "%e %B %Y"
13 long_ordinal: "%e %B %Y"
14 only_day: "%e"
14 only_day: "%e"
15
15
16 day_names: [dimanche, lundi, mardi, mercredi, jeudi, vendredi, samedi]
16 day_names: [dimanche, lundi, mardi, mercredi, jeudi, vendredi, samedi]
17 abbr_day_names: [dim, lun, mar, mer, jeu, ven, sam]
17 abbr_day_names: [dim, lun, mar, mer, jeu, ven, sam]
18
18
19 # Don't forget the nil at the beginning; there's no such thing as a 0th month
19 # Don't forget the nil at the beginning; there's no such thing as a 0th month
20 month_names: [~, janvier, fΓ©vrier, mars, avril, mai, juin, juillet, aoΓ»t, septembre, octobre, novembre, dΓ©cembre]
20 month_names: [~, janvier, fΓ©vrier, mars, avril, mai, juin, juillet, aoΓ»t, septembre, octobre, novembre, dΓ©cembre]
21 abbr_month_names: [~, jan., fΓ©v., mar., avr., mai, juin, juil., aoΓ»t, sept., oct., nov., dΓ©c.]
21 abbr_month_names: [~, jan., fΓ©v., mar., avr., mai, juin, juil., aoΓ»t, sept., oct., nov., dΓ©c.]
22 # Used in date_select and datime_select.
22 # Used in date_select and datime_select.
23 order:
23 order:
24 - :day
24 - :day
25 - :month
25 - :month
26 - :year
26 - :year
27
27
28 time:
28 time:
29 formats:
29 formats:
30 default: "%d/%m/%Y %H:%M"
30 default: "%d/%m/%Y %H:%M"
31 time: "%H:%M"
31 time: "%H:%M"
32 short: "%d %b %H:%M"
32 short: "%d %b %H:%M"
33 long: "%A %d %B %Y %H:%M:%S %Z"
33 long: "%A %d %B %Y %H:%M:%S %Z"
34 long_ordinal: "%A %d %B %Y %H:%M:%S %Z"
34 long_ordinal: "%A %d %B %Y %H:%M:%S %Z"
35 only_second: "%S"
35 only_second: "%S"
36 am: 'am'
36 am: 'am'
37 pm: 'pm'
37 pm: 'pm'
38
38
39 datetime:
39 datetime:
40 distance_in_words:
40 distance_in_words:
41 half_a_minute: "30 secondes"
41 half_a_minute: "30 secondes"
42 less_than_x_seconds:
42 less_than_x_seconds:
43 zero: "moins d'une seconde"
43 zero: "moins d'une seconde"
44 one: "moins d'uneΒ seconde"
44 one: "moins d'uneΒ seconde"
45 other: "moins de %{count}Β secondes"
45 other: "moins de %{count}Β secondes"
46 x_seconds:
46 x_seconds:
47 one: "1Β seconde"
47 one: "1Β seconde"
48 other: "%{count}Β secondes"
48 other: "%{count}Β secondes"
49 less_than_x_minutes:
49 less_than_x_minutes:
50 zero: "moins d'une minute"
50 zero: "moins d'une minute"
51 one: "moins d'uneΒ minute"
51 one: "moins d'uneΒ minute"
52 other: "moins de %{count}Β minutes"
52 other: "moins de %{count}Β minutes"
53 x_minutes:
53 x_minutes:
54 one: "1Β minute"
54 one: "1Β minute"
55 other: "%{count}Β minutes"
55 other: "%{count}Β minutes"
56 about_x_hours:
56 about_x_hours:
57 one: "environ une heure"
57 one: "environ une heure"
58 other: "environ %{count}Β heures"
58 other: "environ %{count}Β heures"
59 x_hours:
59 x_hours:
60 one: "une heure"
60 one: "une heure"
61 other: "%{count}Β heures"
61 other: "%{count}Β heures"
62 x_days:
62 x_days:
63 one: "unΒ jour"
63 one: "unΒ jour"
64 other: "%{count}Β jours"
64 other: "%{count}Β jours"
65 about_x_months:
65 about_x_months:
66 one: "environ un mois"
66 one: "environ un mois"
67 other: "environ %{count}Β mois"
67 other: "environ %{count}Β mois"
68 x_months:
68 x_months:
69 one: "unΒ mois"
69 one: "unΒ mois"
70 other: "%{count}Β mois"
70 other: "%{count}Β mois"
71 about_x_years:
71 about_x_years:
72 one: "environ un an"
72 one: "environ un an"
73 other: "environ %{count}Β ans"
73 other: "environ %{count}Β ans"
74 over_x_years:
74 over_x_years:
75 one: "plus d'un an"
75 one: "plus d'un an"
76 other: "plus de %{count}Β ans"
76 other: "plus de %{count}Β ans"
77 almost_x_years:
77 almost_x_years:
78 one: "presqu'un an"
78 one: "presqu'un an"
79 other: "presque %{count} ans"
79 other: "presque %{count} ans"
80 prompts:
80 prompts:
81 year: "AnnΓ©e"
81 year: "AnnΓ©e"
82 month: "Mois"
82 month: "Mois"
83 day: "Jour"
83 day: "Jour"
84 hour: "Heure"
84 hour: "Heure"
85 minute: "Minute"
85 minute: "Minute"
86 second: "Seconde"
86 second: "Seconde"
87
87
88 number:
88 number:
89 format:
89 format:
90 precision: 3
90 precision: 3
91 separator: ','
91 separator: ','
92 delimiter: 'Β '
92 delimiter: 'Β '
93 currency:
93 currency:
94 format:
94 format:
95 unit: '€'
95 unit: '€'
96 precision: 2
96 precision: 2
97 format: '%nΒ %u'
97 format: '%nΒ %u'
98 human:
98 human:
99 format:
99 format:
100 precision: 3
100 precision: 3
101 storage_units:
101 storage_units:
102 format: "%n %u"
102 format: "%n %u"
103 units:
103 units:
104 byte:
104 byte:
105 one: "octet"
105 one: "octet"
106 other: "octets"
106 other: "octets"
107 kb: "ko"
107 kb: "ko"
108 mb: "Mo"
108 mb: "Mo"
109 gb: "Go"
109 gb: "Go"
110 tb: "To"
110 tb: "To"
111
111
112 support:
112 support:
113 array:
113 array:
114 sentence_connector: 'et'
114 sentence_connector: 'et'
115 skip_last_comma: true
115 skip_last_comma: true
116 word_connector: ", "
116 word_connector: ", "
117 two_words_connector: " et "
117 two_words_connector: " et "
118 last_word_connector: " et "
118 last_word_connector: " et "
119
119
120 activerecord:
120 activerecord:
121 errors:
121 errors:
122 template:
122 template:
123 header:
123 header:
124 one: "Impossible d'enregistrer %{model} : une erreur"
124 one: "Impossible d'enregistrer %{model} : une erreur"
125 other: "Impossible d'enregistrer %{model} : %{count} erreurs."
125 other: "Impossible d'enregistrer %{model} : %{count} erreurs."
126 body: "Veuillez vΓ©rifier les champs suivantsΒ :"
126 body: "Veuillez vΓ©rifier les champs suivantsΒ :"
127 messages:
127 messages:
128 inclusion: "n'est pas inclus(e) dans la liste"
128 inclusion: "n'est pas inclus(e) dans la liste"
129 exclusion: "n'est pas disponible"
129 exclusion: "n'est pas disponible"
130 invalid: "n'est pas valide"
130 invalid: "n'est pas valide"
131 confirmation: "ne concorde pas avec la confirmation"
131 confirmation: "ne concorde pas avec la confirmation"
132 accepted: "doit Γͺtre acceptΓ©(e)"
132 accepted: "doit Γͺtre acceptΓ©(e)"
133 empty: "doit Γͺtre renseignΓ©(e)"
133 empty: "doit Γͺtre renseignΓ©(e)"
134 blank: "doit Γͺtre renseignΓ©(e)"
134 blank: "doit Γͺtre renseignΓ©(e)"
135 too_long: "est trop long (pas plus de %{count} caractères)"
135 too_long: "est trop long (pas plus de %{count} caractères)"
136 too_short: "est trop court (au moins %{count} caractères)"
136 too_short: "est trop court (au moins %{count} caractères)"
137 wrong_length: "ne fait pas la bonne longueur (doit comporter %{count} caractères)"
137 wrong_length: "ne fait pas la bonne longueur (doit comporter %{count} caractères)"
138 taken: "est dΓ©jΓ  utilisΓ©"
138 taken: "est dΓ©jΓ  utilisΓ©"
139 not_a_number: "n'est pas un nombre"
139 not_a_number: "n'est pas un nombre"
140 not_a_date: "n'est pas une date valide"
140 not_a_date: "n'est pas une date valide"
141 greater_than: "doit Γͺtre supΓ©rieur Γ  %{count}"
141 greater_than: "doit Γͺtre supΓ©rieur Γ  %{count}"
142 greater_than_or_equal_to: "doit Γͺtre supΓ©rieur ou Γ©gal Γ  %{count}"
142 greater_than_or_equal_to: "doit Γͺtre supΓ©rieur ou Γ©gal Γ  %{count}"
143 equal_to: "doit Γͺtre Γ©gal Γ  %{count}"
143 equal_to: "doit Γͺtre Γ©gal Γ  %{count}"
144 less_than: "doit Γͺtre infΓ©rieur Γ  %{count}"
144 less_than: "doit Γͺtre infΓ©rieur Γ  %{count}"
145 less_than_or_equal_to: "doit Γͺtre infΓ©rieur ou Γ©gal Γ  %{count}"
145 less_than_or_equal_to: "doit Γͺtre infΓ©rieur ou Γ©gal Γ  %{count}"
146 odd: "doit Γͺtre impair"
146 odd: "doit Γͺtre impair"
147 even: "doit Γͺtre pair"
147 even: "doit Γͺtre pair"
148 greater_than_start_date: "doit Γͺtre postΓ©rieure Γ  la date de dΓ©but"
148 greater_than_start_date: "doit Γͺtre postΓ©rieure Γ  la date de dΓ©but"
149 not_same_project: "n'appartient pas au mΓͺme projet"
149 not_same_project: "n'appartient pas au mΓͺme projet"
150 circular_dependency: "Cette relation crΓ©erait une dΓ©pendance circulaire"
150 circular_dependency: "Cette relation crΓ©erait une dΓ©pendance circulaire"
151 cant_link_an_issue_with_a_descendant: "Une demande ne peut pas Γͺtre liΓ©e Γ  l'une de ses sous-tΓ’ches"
151 cant_link_an_issue_with_a_descendant: "Une demande ne peut pas Γͺtre liΓ©e Γ  l'une de ses sous-tΓ’ches"
152 earlier_than_minimum_start_date: "ne peut pas Γͺtre antΓ©rieure au %{date} Γ  cause des demandes qui prΓ©cΓ¨dent"
152 earlier_than_minimum_start_date: "ne peut pas Γͺtre antΓ©rieure au %{date} Γ  cause des demandes qui prΓ©cΓ¨dent"
153
153
154 actionview_instancetag_blank_option: Choisir
154 actionview_instancetag_blank_option: Choisir
155
155
156 general_text_No: 'Non'
156 general_text_No: 'Non'
157 general_text_Yes: 'Oui'
157 general_text_Yes: 'Oui'
158 general_text_no: 'non'
158 general_text_no: 'non'
159 general_text_yes: 'oui'
159 general_text_yes: 'oui'
160 general_lang_name: 'French (FranΓ§ais)'
160 general_lang_name: 'French (FranΓ§ais)'
161 general_csv_separator: ';'
161 general_csv_separator: ';'
162 general_csv_decimal_separator: ','
162 general_csv_decimal_separator: ','
163 general_csv_encoding: ISO-8859-1
163 general_csv_encoding: ISO-8859-1
164 general_pdf_fontname: freesans
164 general_pdf_fontname: freesans
165 general_pdf_monospaced_fontname: freemono
165 general_pdf_monospaced_fontname: freemono
166 general_first_day_of_week: '1'
166 general_first_day_of_week: '1'
167
167
168 notice_account_updated: Le compte a été mis à jour avec succès.
168 notice_account_updated: Le compte a été mis à jour avec succès.
169 notice_account_invalid_credentials: Identifiant ou mot de passe invalide.
169 notice_account_invalid_credentials: Identifiant ou mot de passe invalide.
170 notice_account_password_updated: Mot de passe mis à jour avec succès.
170 notice_account_password_updated: Mot de passe mis à jour avec succès.
171 notice_account_wrong_password: Mot de passe incorrect
171 notice_account_wrong_password: Mot de passe incorrect
172 notice_account_register_done: Un message contenant les instructions pour activer votre compte vous a Γ©tΓ© envoyΓ© Γ  l'adresse %{email}.
172 notice_account_register_done: Un message contenant les instructions pour activer votre compte vous a Γ©tΓ© envoyΓ© Γ  l'adresse %{email}.
173 notice_account_unknown_email: Aucun compte ne correspond Γ  cette adresse.
173 notice_account_unknown_email: Aucun compte ne correspond Γ  cette adresse.
174 notice_account_not_activated_yet: Vous n'avez pas encore activΓ© votre compte. Si vous voulez recevoir un nouveau message d'activation, veuillez <a href="%{url}">cliquer sur ce lien</a>.
174 notice_account_not_activated_yet: Vous n'avez pas encore activΓ© votre compte. Si vous voulez recevoir un nouveau message d'activation, veuillez <a href="%{url}">cliquer sur ce lien</a>.
175 notice_account_locked: Votre compte est verrouillΓ©.
175 notice_account_locked: Votre compte est verrouillΓ©.
176 notice_can_t_change_password: Ce compte utilise une authentification externe. Impossible de changer le mot de passe.
176 notice_can_t_change_password: Ce compte utilise une authentification externe. Impossible de changer le mot de passe.
177 notice_account_lost_email_sent: Un message contenant les instructions pour choisir un nouveau mot de passe vous a Γ©tΓ© envoyΓ©.
177 notice_account_lost_email_sent: Un message contenant les instructions pour choisir un nouveau mot de passe vous a Γ©tΓ© envoyΓ©.
178 notice_account_activated: Votre compte a Γ©tΓ© activΓ©. Vous pouvez Γ  prΓ©sent vous connecter.
178 notice_account_activated: Votre compte a Γ©tΓ© activΓ©. Vous pouvez Γ  prΓ©sent vous connecter.
179 notice_successful_create: Création effectuée avec succès.
179 notice_successful_create: Création effectuée avec succès.
180 notice_successful_update: Mise à jour effectuée avec succès.
180 notice_successful_update: Mise à jour effectuée avec succès.
181 notice_successful_delete: Suppression effectuée avec succès.
181 notice_successful_delete: Suppression effectuée avec succès.
182 notice_successful_connection: Connexion rΓ©ussie.
182 notice_successful_connection: Connexion rΓ©ussie.
183 notice_file_not_found: "La page Γ  laquelle vous souhaitez accΓ©der n'existe pas ou a Γ©tΓ© supprimΓ©e."
183 notice_file_not_found: "La page Γ  laquelle vous souhaitez accΓ©der n'existe pas ou a Γ©tΓ© supprimΓ©e."
184 notice_locking_conflict: Les donnΓ©es ont Γ©tΓ© mises Γ  jour par un autre utilisateur. Mise Γ  jour impossible.
184 notice_locking_conflict: Les donnΓ©es ont Γ©tΓ© mises Γ  jour par un autre utilisateur. Mise Γ  jour impossible.
185 notice_not_authorized: "Vous n'Γͺtes pas autorisΓ© Γ  accΓ©der Γ  cette page."
185 notice_not_authorized: "Vous n'Γͺtes pas autorisΓ© Γ  accΓ©der Γ  cette page."
186 notice_not_authorized_archived_project: Le projet auquel vous tentez d'accΓ©der a Γ©tΓ© archivΓ©.
186 notice_not_authorized_archived_project: Le projet auquel vous tentez d'accΓ©der a Γ©tΓ© archivΓ©.
187 notice_email_sent: "Un email a Γ©tΓ© envoyΓ© Γ  %{value}"
187 notice_email_sent: "Un email a Γ©tΓ© envoyΓ© Γ  %{value}"
188 notice_email_error: "Erreur lors de l'envoi de l'email (%{value})"
188 notice_email_error: "Erreur lors de l'envoi de l'email (%{value})"
189 notice_feeds_access_key_reseted: "Votre clé d'accès aux flux Atom a été réinitialisée."
189 notice_feeds_access_key_reseted: "Votre clé d'accès aux flux Atom a été réinitialisée."
190 notice_api_access_key_reseted: Votre clé d'accès API a été réinitialisée.
190 notice_api_access_key_reseted: Votre clé d'accès API a été réinitialisée.
191 notice_failed_to_save_issues: "%{count} demande(s) sur les %{total} sΓ©lectionnΓ©es n'ont pas pu Γͺtre mise(s) Γ  jour : %{ids}."
191 notice_failed_to_save_issues: "%{count} demande(s) sur les %{total} sΓ©lectionnΓ©es n'ont pas pu Γͺtre mise(s) Γ  jour : %{ids}."
192 notice_failed_to_save_time_entries: "%{count} temps passΓ©(s) sur les %{total} sΓ©lectionnΓ©s n'ont pas pu Γͺtre mis Γ  jour: %{ids}."
192 notice_failed_to_save_time_entries: "%{count} temps passΓ©(s) sur les %{total} sΓ©lectionnΓ©s n'ont pas pu Γͺtre mis Γ  jour: %{ids}."
193 notice_failed_to_save_members: "Erreur lors de la sauvegarde des membres: %{errors}."
193 notice_failed_to_save_members: "Erreur lors de la sauvegarde des membres: %{errors}."
194 notice_no_issue_selected: "Aucune demande sΓ©lectionnΓ©e ! Cochez les demandes que vous voulez mettre Γ  jour."
194 notice_no_issue_selected: "Aucune demande sΓ©lectionnΓ©e ! Cochez les demandes que vous voulez mettre Γ  jour."
195 notice_account_pending: "Votre compte a été créé et attend l'approbation de l'administrateur."
195 notice_account_pending: "Votre compte a été créé et attend l'approbation de l'administrateur."
196 notice_default_data_loaded: Paramétrage par défaut chargé avec succès.
196 notice_default_data_loaded: Paramétrage par défaut chargé avec succès.
197 notice_unable_delete_version: Impossible de supprimer cette version.
197 notice_unable_delete_version: Impossible de supprimer cette version.
198 notice_unable_delete_time_entry: Impossible de supprimer le temps passΓ©.
198 notice_unable_delete_time_entry: Impossible de supprimer le temps passΓ©.
199 notice_issue_done_ratios_updated: L'avancement des demandes a Γ©tΓ© mis Γ  jour.
199 notice_issue_done_ratios_updated: L'avancement des demandes a Γ©tΓ© mis Γ  jour.
200 notice_gantt_chart_truncated: "Le diagramme a Γ©tΓ© tronquΓ© car il excΓ¨de le nombre maximal d'Γ©lΓ©ments pouvant Γͺtre affichΓ©s (%{max})"
200 notice_gantt_chart_truncated: "Le diagramme a Γ©tΓ© tronquΓ© car il excΓ¨de le nombre maximal d'Γ©lΓ©ments pouvant Γͺtre affichΓ©s (%{max})"
201 notice_issue_successful_create: "Demande %{id} créée."
201 notice_issue_successful_create: "Demande %{id} créée."
202 notice_issue_update_conflict: "La demande a Γ©tΓ© mise Γ  jour par un autre utilisateur pendant que vous la modifiez."
202 notice_issue_update_conflict: "La demande a Γ©tΓ© mise Γ  jour par un autre utilisateur pendant que vous la modifiez."
203 notice_account_deleted: "Votre compte a Γ©tΓ© dΓ©finitivement supprimΓ©."
203 notice_account_deleted: "Votre compte a Γ©tΓ© dΓ©finitivement supprimΓ©."
204 notice_user_successful_create: "Utilisateur %{id} créé."
204 notice_user_successful_create: "Utilisateur %{id} créé."
205 notice_new_password_must_be_different: Votre nouveau mot de passe doit Γͺtre diffΓ©rent de votre mot de passe actuel
205 notice_new_password_must_be_different: Votre nouveau mot de passe doit Γͺtre diffΓ©rent de votre mot de passe actuel
206 notice_import_finished: "%{count} Γ©lΓ©ments ont Γ©tΓ© importΓ©(s)"
206 notice_import_finished: "%{count} Γ©lΓ©ments ont Γ©tΓ© importΓ©(s)"
207 notice_import_finished_with_errors: "%{count} Γ©lΓ©ment(s) sur %{total} n'ont pas pu Γͺtre importΓ©(s)"
207 notice_import_finished_with_errors: "%{count} Γ©lΓ©ment(s) sur %{total} n'ont pas pu Γͺtre importΓ©(s)"
208
208
209 error_can_t_load_default_data: "Une erreur s'est produite lors du chargement du paramΓ©trage : %{value}"
209 error_can_t_load_default_data: "Une erreur s'est produite lors du chargement du paramΓ©trage : %{value}"
210 error_scm_not_found: "L'entrΓ©e et/ou la rΓ©vision demandΓ©e n'existe pas dans le dΓ©pΓ΄t."
210 error_scm_not_found: "L'entrΓ©e et/ou la rΓ©vision demandΓ©e n'existe pas dans le dΓ©pΓ΄t."
211 error_scm_command_failed: "Une erreur s'est produite lors de l'accès au dépôt : %{value}"
211 error_scm_command_failed: "Une erreur s'est produite lors de l'accès au dépôt : %{value}"
212 error_scm_annotate: "L'entrΓ©e n'existe pas ou ne peut pas Γͺtre annotΓ©e."
212 error_scm_annotate: "L'entrΓ©e n'existe pas ou ne peut pas Γͺtre annotΓ©e."
213 error_scm_annotate_big_text_file: Cette entrΓ©e ne peut pas Γͺtre annotΓ©e car elle excΓ¨de la taille maximale.
213 error_scm_annotate_big_text_file: Cette entrΓ©e ne peut pas Γͺtre annotΓ©e car elle excΓ¨de la taille maximale.
214 error_issue_not_found_in_project: "La demande n'existe pas ou n'appartient pas Γ  ce projet"
214 error_issue_not_found_in_project: "La demande n'existe pas ou n'appartient pas Γ  ce projet"
215 error_no_tracker_in_project: "Aucun tracker n'est associΓ© Γ  ce projet. VΓ©rifier la configuration du projet."
215 error_no_tracker_in_project: "Aucun tracker n'est associΓ© Γ  ce projet. VΓ©rifier la configuration du projet."
216 error_no_default_issue_status: "Aucun statut de demande n'est dΓ©fini par dΓ©faut. VΓ©rifier votre configuration (Administration -> Statuts de demandes)."
216 error_no_default_issue_status: "Aucun statut de demande n'est dΓ©fini par dΓ©faut. VΓ©rifier votre configuration (Administration -> Statuts de demandes)."
217 error_can_not_delete_custom_field: Impossible de supprimer le champ personnalisΓ©
217 error_can_not_delete_custom_field: Impossible de supprimer le champ personnalisΓ©
218 error_can_not_delete_tracker: Ce tracker contient des demandes et ne peut pas Γͺtre supprimΓ©.
218 error_can_not_delete_tracker: Ce tracker contient des demandes et ne peut pas Γͺtre supprimΓ©.
219 error_can_not_remove_role: Ce rΓ΄le est utilisΓ© et ne peut pas Γͺtre supprimΓ©.
219 error_can_not_remove_role: Ce rΓ΄le est utilisΓ© et ne peut pas Γͺtre supprimΓ©.
220 error_can_not_reopen_issue_on_closed_version: 'Une demande assignΓ©e Γ  une version fermΓ©e ne peut pas Γͺtre rΓ©ouverte'
220 error_can_not_reopen_issue_on_closed_version: 'Une demande assignΓ©e Γ  une version fermΓ©e ne peut pas Γͺtre rΓ©ouverte'
221 error_can_not_archive_project: "Ce projet ne peut pas Γͺtre archivΓ©"
221 error_can_not_archive_project: "Ce projet ne peut pas Γͺtre archivΓ©"
222 error_issue_done_ratios_not_updated: L'avancement des demandes n'a pas pu Γͺtre mis Γ  jour.
222 error_issue_done_ratios_not_updated: L'avancement des demandes n'a pas pu Γͺtre mis Γ  jour.
223 error_workflow_copy_source: 'Veuillez sΓ©lectionner un tracker et/ou un rΓ΄le source'
223 error_workflow_copy_source: 'Veuillez sΓ©lectionner un tracker et/ou un rΓ΄le source'
224 error_workflow_copy_target: 'Veuillez sΓ©lectionner les trackers et rΓ΄les cibles'
224 error_workflow_copy_target: 'Veuillez sΓ©lectionner les trackers et rΓ΄les cibles'
225 error_unable_delete_issue_status: Impossible de supprimer le statut de demande
225 error_unable_delete_issue_status: Impossible de supprimer le statut de demande
226 error_unable_to_connect: Connexion impossible (%{value})
226 error_unable_to_connect: Connexion impossible (%{value})
227 error_attachment_too_big: Ce fichier ne peut pas Γͺtre attachΓ© car il excΓ¨de la taille maximale autorisΓ©e (%{max_size})
227 error_attachment_too_big: Ce fichier ne peut pas Γͺtre attachΓ© car il excΓ¨de la taille maximale autorisΓ©e (%{max_size})
228 error_session_expired: "Votre session a expirΓ©. Veuillez vous reconnecter."
228 error_session_expired: "Votre session a expirΓ©. Veuillez vous reconnecter."
229 warning_attachments_not_saved: "%{count} fichier(s) n'ont pas pu Γͺtre sauvegardΓ©s."
229 warning_attachments_not_saved: "%{count} fichier(s) n'ont pas pu Γͺtre sauvegardΓ©s."
230 error_password_expired: "Votre mot de passe a expirΓ© ou nΓ©cessite d'Γͺtre changΓ©."
230 error_password_expired: "Votre mot de passe a expirΓ© ou nΓ©cessite d'Γͺtre changΓ©."
231 error_invalid_file_encoding: "Le fichier n'est pas un fichier %{encoding} valide"
231 error_invalid_file_encoding: "Le fichier n'est pas un fichier %{encoding} valide"
232 error_invalid_csv_file_or_settings: "Le fichier n'est pas un fichier CSV ou n'est pas conforme aux paramètres sélectionnés"
232 error_invalid_csv_file_or_settings: "Le fichier n'est pas un fichier CSV ou n'est pas conforme aux paramètres sélectionnés"
233 error_can_not_read_import_file: "Une erreur est survenue lors de la lecture du fichier Γ  importer"
233 error_can_not_read_import_file: "Une erreur est survenue lors de la lecture du fichier Γ  importer"
234 error_attachment_extension_not_allowed: "L'extension %{extension} n'est pas autorisΓ©e"
234 error_attachment_extension_not_allowed: "L'extension %{extension} n'est pas autorisΓ©e"
235 error_ldap_bind_credentials: "Identifiant ou mot de passe LDAP incorrect"
235 error_ldap_bind_credentials: "Identifiant ou mot de passe LDAP incorrect"
236 error_no_tracker_allowed_for_new_issue_in_project: "Le projet ne dispose d'aucun tracker sur lequel vous pouvez crΓ©er une demande"
236 error_no_tracker_allowed_for_new_issue_in_project: "Le projet ne dispose d'aucun tracker sur lequel vous pouvez crΓ©er une demande"
237 error_no_projects_with_tracker_allowed_for_new_issue: "Aucun projet ne dispose d'un tracker sur lequel vous pouvez crΓ©er une demande"
237 error_no_projects_with_tracker_allowed_for_new_issue: "Aucun projet ne dispose d'un tracker sur lequel vous pouvez crΓ©er une demande"
238
238
239 mail_subject_lost_password: "Votre mot de passe %{value}"
239 mail_subject_lost_password: "Votre mot de passe %{value}"
240 mail_body_lost_password: 'Pour changer votre mot de passe, cliquez sur le lien suivant :'
240 mail_body_lost_password: 'Pour changer votre mot de passe, cliquez sur le lien suivant :'
241 mail_subject_register: "Activation de votre compte %{value}"
241 mail_subject_register: "Activation de votre compte %{value}"
242 mail_body_register: 'Pour activer votre compte, cliquez sur le lien suivant :'
242 mail_body_register: 'Pour activer votre compte, cliquez sur le lien suivant :'
243 mail_body_account_information_external: "Vous pouvez utiliser votre compte %{value} pour vous connecter."
243 mail_body_account_information_external: "Vous pouvez utiliser votre compte %{value} pour vous connecter."
244 mail_body_account_information: Paramètres de connexion de votre compte
244 mail_body_account_information: Paramètres de connexion de votre compte
245 mail_subject_account_activation_request: "Demande d'activation d'un compte %{value}"
245 mail_subject_account_activation_request: "Demande d'activation d'un compte %{value}"
246 mail_body_account_activation_request: "Un nouvel utilisateur (%{value}) s'est inscrit. Son compte nΓ©cessite votre approbation :"
246 mail_body_account_activation_request: "Un nouvel utilisateur (%{value}) s'est inscrit. Son compte nΓ©cessite votre approbation :"
247 mail_subject_reminder: "%{count} demande(s) arrivent Γ  Γ©chΓ©ance (%{days})"
247 mail_subject_reminder: "%{count} demande(s) arrivent Γ  Γ©chΓ©ance (%{days})"
248 mail_body_reminder: "%{count} demande(s) qui vous sont assignΓ©es arrivent Γ  Γ©chΓ©ance dans les %{days} prochains jours :"
248 mail_body_reminder: "%{count} demande(s) qui vous sont assignΓ©es arrivent Γ  Γ©chΓ©ance dans les %{days} prochains jours :"
249 mail_subject_wiki_content_added: "Page wiki '%{id}' ajoutΓ©e"
249 mail_subject_wiki_content_added: "Page wiki '%{id}' ajoutΓ©e"
250 mail_body_wiki_content_added: "La page wiki '%{id}' a Γ©tΓ© ajoutΓ©e par %{author}."
250 mail_body_wiki_content_added: "La page wiki '%{id}' a Γ©tΓ© ajoutΓ©e par %{author}."
251 mail_subject_wiki_content_updated: "Page wiki '%{id}' mise Γ  jour"
251 mail_subject_wiki_content_updated: "Page wiki '%{id}' mise Γ  jour"
252 mail_body_wiki_content_updated: "La page wiki '%{id}' a Γ©tΓ© mise Γ  jour par %{author}."
252 mail_body_wiki_content_updated: "La page wiki '%{id}' a Γ©tΓ© mise Γ  jour par %{author}."
253 mail_body_settings_updated: "Les paramètres suivants ont été modifiés :"
253 mail_body_settings_updated: "Les paramètres suivants ont été modifiés :"
254 mail_body_password_updated: "Votre mot de passe a Γ©tΓ© changΓ©."
254 mail_body_password_updated: "Votre mot de passe a Γ©tΓ© changΓ©."
255
255
256 field_name: Nom
256 field_name: Nom
257 field_description: Description
257 field_description: Description
258 field_summary: RΓ©sumΓ©
258 field_summary: RΓ©sumΓ©
259 field_is_required: Obligatoire
259 field_is_required: Obligatoire
260 field_firstname: PrΓ©nom
260 field_firstname: PrΓ©nom
261 field_lastname: Nom
261 field_lastname: Nom
262 field_mail: Email
262 field_mail: Email
263 field_address: Email
263 field_address: Email
264 field_filename: Fichier
264 field_filename: Fichier
265 field_filesize: Taille
265 field_filesize: Taille
266 field_downloads: TΓ©lΓ©chargements
266 field_downloads: TΓ©lΓ©chargements
267 field_author: Auteur
267 field_author: Auteur
268 field_created_on: Créé
268 field_created_on: Créé
269 field_updated_on: Mis-Γ -jour
269 field_updated_on: Mis-Γ -jour
270 field_closed_on: FermΓ©
270 field_closed_on: FermΓ©
271 field_field_format: Format
271 field_field_format: Format
272 field_is_for_all: Pour tous les projets
272 field_is_for_all: Pour tous les projets
273 field_possible_values: Valeurs possibles
273 field_possible_values: Valeurs possibles
274 field_regexp: Expression régulière
274 field_regexp: Expression régulière
275 field_min_length: Longueur minimum
275 field_min_length: Longueur minimum
276 field_max_length: Longueur maximum
276 field_max_length: Longueur maximum
277 field_value: Valeur
277 field_value: Valeur
278 field_category: CatΓ©gorie
278 field_category: CatΓ©gorie
279 field_title: Titre
279 field_title: Titre
280 field_project: Projet
280 field_project: Projet
281 field_issue: Demande
281 field_issue: Demande
282 field_status: Statut
282 field_status: Statut
283 field_notes: Notes
283 field_notes: Notes
284 field_is_closed: Demande fermΓ©e
284 field_is_closed: Demande fermΓ©e
285 field_is_default: Valeur par dΓ©faut
285 field_is_default: Valeur par dΓ©faut
286 field_tracker: Tracker
286 field_tracker: Tracker
287 field_subject: Sujet
287 field_subject: Sujet
288 field_due_date: EchΓ©ance
288 field_due_date: EchΓ©ance
289 field_assigned_to: AssignΓ© Γ 
289 field_assigned_to: AssignΓ© Γ 
290 field_priority: PrioritΓ©
290 field_priority: PrioritΓ©
291 field_fixed_version: Version cible
291 field_fixed_version: Version cible
292 field_user: Utilisateur
292 field_user: Utilisateur
293 field_principal: Principal
293 field_principal: Principal
294 field_role: RΓ΄le
294 field_role: RΓ΄le
295 field_homepage: Site web
295 field_homepage: Site web
296 field_is_public: Public
296 field_is_public: Public
297 field_parent: Sous-projet de
297 field_parent: Sous-projet de
298 field_is_in_roadmap: Demandes affichΓ©es dans la roadmap
298 field_is_in_roadmap: Demandes affichΓ©es dans la roadmap
299 field_login: Identifiant
299 field_login: Identifiant
300 field_mail_notification: Notifications par mail
300 field_mail_notification: Notifications par mail
301 field_admin: Administrateur
301 field_admin: Administrateur
302 field_last_login_on: Dernière connexion
302 field_last_login_on: Dernière connexion
303 field_language: Langue
303 field_language: Langue
304 field_effective_date: Date
304 field_effective_date: Date
305 field_password: Mot de passe
305 field_password: Mot de passe
306 field_new_password: Nouveau mot de passe
306 field_new_password: Nouveau mot de passe
307 field_password_confirmation: Confirmation
307 field_password_confirmation: Confirmation
308 field_version: Version
308 field_version: Version
309 field_type: Type
309 field_type: Type
310 field_host: HΓ΄te
310 field_host: HΓ΄te
311 field_port: Port
311 field_port: Port
312 field_account: Compte
312 field_account: Compte
313 field_base_dn: Base DN
313 field_base_dn: Base DN
314 field_attr_login: Attribut Identifiant
314 field_attr_login: Attribut Identifiant
315 field_attr_firstname: Attribut PrΓ©nom
315 field_attr_firstname: Attribut PrΓ©nom
316 field_attr_lastname: Attribut Nom
316 field_attr_lastname: Attribut Nom
317 field_attr_mail: Attribut Email
317 field_attr_mail: Attribut Email
318 field_onthefly: CrΓ©ation des utilisateurs Γ  la volΓ©e
318 field_onthefly: CrΓ©ation des utilisateurs Γ  la volΓ©e
319 field_start_date: DΓ©but
319 field_start_date: DΓ©but
320 field_done_ratio: "% rΓ©alisΓ©"
320 field_done_ratio: "% rΓ©alisΓ©"
321 field_auth_source: Mode d'authentification
321 field_auth_source: Mode d'authentification
322 field_hide_mail: Cacher mon adresse mail
322 field_hide_mail: Cacher mon adresse mail
323 field_comments: Commentaire
323 field_comments: Commentaire
324 field_url: URL
324 field_url: URL
325 field_start_page: Page de dΓ©marrage
325 field_start_page: Page de dΓ©marrage
326 field_subproject: Sous-projet
326 field_subproject: Sous-projet
327 field_hours: Heures
327 field_hours: Heures
328 field_activity: ActivitΓ©
328 field_activity: ActivitΓ©
329 field_spent_on: Date
329 field_spent_on: Date
330 field_identifier: Identifiant
330 field_identifier: Identifiant
331 field_is_filter: UtilisΓ© comme filtre
331 field_is_filter: UtilisΓ© comme filtre
332 field_issue_to: Demande liΓ©e
332 field_issue_to: Demande liΓ©e
333 field_delay: Retard
333 field_delay: Retard
334 field_assignable: Demandes assignables Γ  ce rΓ΄le
334 field_assignable: Demandes assignables Γ  ce rΓ΄le
335 field_redirect_existing_links: Rediriger les liens existants
335 field_redirect_existing_links: Rediriger les liens existants
336 field_estimated_hours: Temps estimΓ©
336 field_estimated_hours: Temps estimΓ©
337 field_column_names: Colonnes
337 field_column_names: Colonnes
338 field_time_entries: Temps passΓ©
338 field_time_entries: Temps passΓ©
339 field_time_zone: Fuseau horaire
339 field_time_zone: Fuseau horaire
340 field_searchable: UtilisΓ© pour les recherches
340 field_searchable: UtilisΓ© pour les recherches
341 field_default_value: Valeur par dΓ©faut
341 field_default_value: Valeur par dΓ©faut
342 field_comments_sorting: Afficher les commentaires
342 field_comments_sorting: Afficher les commentaires
343 field_parent_title: Page parent
343 field_parent_title: Page parent
344 field_editable: Modifiable
344 field_editable: Modifiable
345 field_watcher: Observateur
345 field_watcher: Observateur
346 field_identity_url: URL OpenID
346 field_identity_url: URL OpenID
347 field_content: Contenu
347 field_content: Contenu
348 field_group_by: Grouper par
348 field_group_by: Grouper par
349 field_sharing: Partage
349 field_sharing: Partage
350 field_parent_issue: TΓ’che parente
350 field_parent_issue: TΓ’che parente
351 field_member_of_group: Groupe de l'assignΓ©
351 field_member_of_group: Groupe de l'assignΓ©
352 field_assigned_to_role: RΓ΄le de l'assignΓ©
352 field_assigned_to_role: RΓ΄le de l'assignΓ©
353 field_text: Champ texte
353 field_text: Champ texte
354 field_visible: Visible
354 field_visible: Visible
355 field_warn_on_leaving_unsaved: "M'avertir lorsque je quitte une page contenant du texte non sauvegardΓ©"
355 field_warn_on_leaving_unsaved: "M'avertir lorsque je quitte une page contenant du texte non sauvegardΓ©"
356 field_issues_visibility: VisibilitΓ© des demandes
356 field_issues_visibility: VisibilitΓ© des demandes
357 field_is_private: PrivΓ©e
357 field_is_private: PrivΓ©e
358 field_commit_logs_encoding: Encodage des messages de commit
358 field_commit_logs_encoding: Encodage des messages de commit
359 field_scm_path_encoding: Encodage des chemins
359 field_scm_path_encoding: Encodage des chemins
360 field_path_to_repository: Chemin du dΓ©pΓ΄t
360 field_path_to_repository: Chemin du dΓ©pΓ΄t
361 field_root_directory: RΓ©pertoire racine
361 field_root_directory: RΓ©pertoire racine
362 field_cvsroot: CVSROOT
362 field_cvsroot: CVSROOT
363 field_cvs_module: Module
363 field_cvs_module: Module
364 field_repository_is_default: DΓ©pΓ΄t principal
364 field_repository_is_default: DΓ©pΓ΄t principal
365 field_multiple: Valeurs multiples
365 field_multiple: Valeurs multiples
366 field_auth_source_ldap_filter: Filtre LDAP
366 field_auth_source_ldap_filter: Filtre LDAP
367 field_core_fields: Champs standards
367 field_core_fields: Champs standards
368 field_timeout: "Timeout (en secondes)"
368 field_timeout: "Timeout (en secondes)"
369 field_board_parent: Forum parent
369 field_board_parent: Forum parent
370 field_private_notes: Notes privΓ©es
370 field_private_notes: Notes privΓ©es
371 field_inherit_members: HΓ©riter les membres
371 field_inherit_members: HΓ©riter les membres
372 field_generate_password: GΓ©nΓ©rer un mot de passe
372 field_generate_password: GΓ©nΓ©rer un mot de passe
373 field_must_change_passwd: Doit changer de mot de passe Γ  la prochaine connexion
373 field_must_change_passwd: Doit changer de mot de passe Γ  la prochaine connexion
374 field_default_status: Statut par dΓ©faut
374 field_default_status: Statut par dΓ©faut
375 field_users_visibility: VisibilitΓ© des utilisateurs
375 field_users_visibility: VisibilitΓ© des utilisateurs
376 field_time_entries_visibility: VisibilitΓ© du temps passΓ©
376 field_time_entries_visibility: VisibilitΓ© du temps passΓ©
377 field_total_estimated_hours: Temps estimΓ© total
377 field_total_estimated_hours: Temps estimΓ© total
378 field_default_version: Version par dΓ©faut
378 field_default_version: Version par dΓ©faut
379 field_textarea_font: Police utilisΓ©e pour les champs texte
379
380
380 setting_app_title: Titre de l'application
381 setting_app_title: Titre de l'application
381 setting_app_subtitle: Sous-titre de l'application
382 setting_app_subtitle: Sous-titre de l'application
382 setting_welcome_text: Texte d'accueil
383 setting_welcome_text: Texte d'accueil
383 setting_default_language: Langue par dΓ©faut
384 setting_default_language: Langue par dΓ©faut
384 setting_login_required: Authentification obligatoire
385 setting_login_required: Authentification obligatoire
385 setting_self_registration: Inscription des nouveaux utilisateurs
386 setting_self_registration: Inscription des nouveaux utilisateurs
386 setting_attachment_max_size: Taille maximale des fichiers
387 setting_attachment_max_size: Taille maximale des fichiers
387 setting_issues_export_limit: Limite d'exportation des demandes
388 setting_issues_export_limit: Limite d'exportation des demandes
388 setting_mail_from: Adresse d'Γ©mission
389 setting_mail_from: Adresse d'Γ©mission
389 setting_bcc_recipients: Destinataires en copie cachΓ©e (cci)
390 setting_bcc_recipients: Destinataires en copie cachΓ©e (cci)
390 setting_plain_text_mail: Mail en texte brut (non HTML)
391 setting_plain_text_mail: Mail en texte brut (non HTML)
391 setting_host_name: Nom d'hΓ΄te et chemin
392 setting_host_name: Nom d'hΓ΄te et chemin
392 setting_text_formatting: Formatage du texte
393 setting_text_formatting: Formatage du texte
393 setting_wiki_compression: Compression de l'historique des pages wiki
394 setting_wiki_compression: Compression de l'historique des pages wiki
394 setting_feeds_limit: Nombre maximal d'Γ©lΓ©ments dans les flux Atom
395 setting_feeds_limit: Nombre maximal d'Γ©lΓ©ments dans les flux Atom
395 setting_default_projects_public: DΓ©finir les nouveaux projets comme publics par dΓ©faut
396 setting_default_projects_public: DΓ©finir les nouveaux projets comme publics par dΓ©faut
396 setting_autofetch_changesets: RΓ©cupΓ©ration automatique des commits
397 setting_autofetch_changesets: RΓ©cupΓ©ration automatique des commits
397 setting_sys_api_enabled: Activer les WS pour la gestion des dΓ©pΓ΄ts
398 setting_sys_api_enabled: Activer les WS pour la gestion des dΓ©pΓ΄ts
398 setting_commit_ref_keywords: Mots-clΓ©s de rΓ©fΓ©rencement
399 setting_commit_ref_keywords: Mots-clΓ©s de rΓ©fΓ©rencement
399 setting_commit_fix_keywords: Mots-clΓ©s de rΓ©solution
400 setting_commit_fix_keywords: Mots-clΓ©s de rΓ©solution
400 setting_autologin: DurΓ©e maximale de connexion automatique
401 setting_autologin: DurΓ©e maximale de connexion automatique
401 setting_date_format: Format de date
402 setting_date_format: Format de date
402 setting_time_format: Format d'heure
403 setting_time_format: Format d'heure
403 setting_cross_project_issue_relations: Autoriser les relations entre demandes de diffΓ©rents projets
404 setting_cross_project_issue_relations: Autoriser les relations entre demandes de diffΓ©rents projets
404 setting_cross_project_subtasks: Autoriser les sous-tΓ’ches dans des projets diffΓ©rents
405 setting_cross_project_subtasks: Autoriser les sous-tΓ’ches dans des projets diffΓ©rents
405 setting_issue_list_default_columns: Colonnes affichΓ©es par dΓ©faut sur la liste des demandes
406 setting_issue_list_default_columns: Colonnes affichΓ©es par dΓ©faut sur la liste des demandes
406 setting_repositories_encodings: Encodages des fichiers et des dΓ©pΓ΄ts
407 setting_repositories_encodings: Encodages des fichiers et des dΓ©pΓ΄ts
407 setting_emails_header: En-tΓͺte des emails
408 setting_emails_header: En-tΓͺte des emails
408 setting_emails_footer: Pied-de-page des emails
409 setting_emails_footer: Pied-de-page des emails
409 setting_protocol: Protocole
410 setting_protocol: Protocole
410 setting_per_page_options: Options d'objets affichΓ©s par page
411 setting_per_page_options: Options d'objets affichΓ©s par page
411 setting_user_format: Format d'affichage des utilisateurs
412 setting_user_format: Format d'affichage des utilisateurs
412 setting_activity_days_default: Nombre de jours affichΓ©s sur l'activitΓ© des projets
413 setting_activity_days_default: Nombre de jours affichΓ©s sur l'activitΓ© des projets
413 setting_display_subprojects_issues: Afficher par dΓ©faut les demandes des sous-projets sur les projets principaux
414 setting_display_subprojects_issues: Afficher par dΓ©faut les demandes des sous-projets sur les projets principaux
414 setting_enabled_scm: SCM activΓ©s
415 setting_enabled_scm: SCM activΓ©s
415 setting_mail_handler_body_delimiters: "Tronquer les emails après l'une de ces lignes"
416 setting_mail_handler_body_delimiters: "Tronquer les emails après l'une de ces lignes"
416 setting_mail_handler_api_enabled: "Activer le WS pour la rΓ©ception d'emails"
417 setting_mail_handler_api_enabled: "Activer le WS pour la rΓ©ception d'emails"
417 setting_mail_handler_api_key: ClΓ© de protection de l'API
418 setting_mail_handler_api_key: ClΓ© de protection de l'API
418 setting_sequential_project_identifiers: GΓ©nΓ©rer des identifiants de projet sΓ©quentiels
419 setting_sequential_project_identifiers: GΓ©nΓ©rer des identifiants de projet sΓ©quentiels
419 setting_gravatar_enabled: Afficher les Gravatar des utilisateurs
420 setting_gravatar_enabled: Afficher les Gravatar des utilisateurs
420 setting_gravatar_default: Image Gravatar par dΓ©faut
421 setting_gravatar_default: Image Gravatar par dΓ©faut
421 setting_diff_max_lines_displayed: Nombre maximum de lignes de diff affichΓ©es
422 setting_diff_max_lines_displayed: Nombre maximum de lignes de diff affichΓ©es
422 setting_file_max_size_displayed: Taille maximum des fichiers texte affichΓ©s en ligne
423 setting_file_max_size_displayed: Taille maximum des fichiers texte affichΓ©s en ligne
423 setting_repository_log_display_limit: "Nombre maximum de rΓ©visions affichΓ©es sur l'historique d'un fichier"
424 setting_repository_log_display_limit: "Nombre maximum de rΓ©visions affichΓ©es sur l'historique d'un fichier"
424 setting_openid: "Autoriser l'authentification et l'enregistrement OpenID"
425 setting_openid: "Autoriser l'authentification et l'enregistrement OpenID"
425 setting_password_max_age: Expiration des mots de passe après
426 setting_password_max_age: Expiration des mots de passe après
426 setting_password_min_length: Longueur minimum des mots de passe
427 setting_password_min_length: Longueur minimum des mots de passe
427 setting_new_project_user_role_id: RΓ΄le donnΓ© Γ  un utilisateur non-administrateur qui crΓ©e un projet
428 setting_new_project_user_role_id: RΓ΄le donnΓ© Γ  un utilisateur non-administrateur qui crΓ©e un projet
428 setting_default_projects_modules: Modules activΓ©s par dΓ©faut pour les nouveaux projets
429 setting_default_projects_modules: Modules activΓ©s par dΓ©faut pour les nouveaux projets
429 setting_issue_done_ratio: Calcul de l'avancement des demandes
430 setting_issue_done_ratio: Calcul de l'avancement des demandes
430 setting_issue_done_ratio_issue_field: 'Utiliser le champ % effectuΓ©'
431 setting_issue_done_ratio_issue_field: 'Utiliser le champ % effectuΓ©'
431 setting_issue_done_ratio_issue_status: Utiliser le statut
432 setting_issue_done_ratio_issue_status: Utiliser le statut
432 setting_start_of_week: Jour de dΓ©but des calendriers
433 setting_start_of_week: Jour de dΓ©but des calendriers
433 setting_rest_api_enabled: Activer l'API REST
434 setting_rest_api_enabled: Activer l'API REST
434 setting_cache_formatted_text: Mettre en cache le texte formatΓ©
435 setting_cache_formatted_text: Mettre en cache le texte formatΓ©
435 setting_default_notification_option: Option de notification par dΓ©faut
436 setting_default_notification_option: Option de notification par dΓ©faut
436 setting_commit_logtime_enabled: Permettre la saisie de temps
437 setting_commit_logtime_enabled: Permettre la saisie de temps
437 setting_commit_logtime_activity_id: ActivitΓ© pour le temps saisi
438 setting_commit_logtime_activity_id: ActivitΓ© pour le temps saisi
438 setting_gantt_items_limit: Nombre maximum d'Γ©lΓ©ments affichΓ©s sur le gantt
439 setting_gantt_items_limit: Nombre maximum d'Γ©lΓ©ments affichΓ©s sur le gantt
439 setting_issue_group_assignment: Permettre l'assignation des demandes aux groupes
440 setting_issue_group_assignment: Permettre l'assignation des demandes aux groupes
440 setting_default_issue_start_date_to_creation_date: Donner Γ  la date de dΓ©but d'une nouvelle demande la valeur de la date du jour
441 setting_default_issue_start_date_to_creation_date: Donner Γ  la date de dΓ©but d'une nouvelle demande la valeur de la date du jour
441 setting_commit_cross_project_ref: Permettre le rΓ©fΓ©rencement et la rΓ©solution des demandes de tous les autres projets
442 setting_commit_cross_project_ref: Permettre le rΓ©fΓ©rencement et la rΓ©solution des demandes de tous les autres projets
442 setting_unsubscribe: Permettre aux utilisateurs de supprimer leur propre compte
443 setting_unsubscribe: Permettre aux utilisateurs de supprimer leur propre compte
443 setting_session_lifetime: DurΓ©e de vie maximale des sessions
444 setting_session_lifetime: DurΓ©e de vie maximale des sessions
444 setting_session_timeout: DurΓ©e maximale d'inactivitΓ©
445 setting_session_timeout: DurΓ©e maximale d'inactivitΓ©
445 setting_thumbnails_enabled: Afficher les vignettes des images
446 setting_thumbnails_enabled: Afficher les vignettes des images
446 setting_thumbnails_size: Taille des vignettes (en pixels)
447 setting_thumbnails_size: Taille des vignettes (en pixels)
447 setting_non_working_week_days: Jours non travaillΓ©s
448 setting_non_working_week_days: Jours non travaillΓ©s
448 setting_jsonp_enabled: Activer le support JSONP
449 setting_jsonp_enabled: Activer le support JSONP
449 setting_default_projects_tracker_ids: Trackers par dΓ©faut pour les nouveaux projets
450 setting_default_projects_tracker_ids: Trackers par dΓ©faut pour les nouveaux projets
450 setting_mail_handler_excluded_filenames: Exclure les fichiers attachΓ©s par leur nom
451 setting_mail_handler_excluded_filenames: Exclure les fichiers attachΓ©s par leur nom
451 setting_force_default_language_for_anonymous: Forcer la langue par dΓ©fault pour les utilisateurs anonymes
452 setting_force_default_language_for_anonymous: Forcer la langue par dΓ©fault pour les utilisateurs anonymes
452 setting_force_default_language_for_loggedin: Forcer la langue par dΓ©fault pour les utilisateurs identifiΓ©s
453 setting_force_default_language_for_loggedin: Forcer la langue par dΓ©fault pour les utilisateurs identifiΓ©s
453 setting_link_copied_issue: Lier les demandes lors de la copie
454 setting_link_copied_issue: Lier les demandes lors de la copie
454 setting_max_additional_emails: Nombre maximal d'adresses email additionnelles
455 setting_max_additional_emails: Nombre maximal d'adresses email additionnelles
455 setting_search_results_per_page: RΓ©sultats de recherche affichΓ©s par page
456 setting_search_results_per_page: RΓ©sultats de recherche affichΓ©s par page
456 setting_attachment_extensions_allowed: Extensions autorisΓ©es
457 setting_attachment_extensions_allowed: Extensions autorisΓ©es
457 setting_attachment_extensions_denied: Extensions non autorisΓ©es
458 setting_attachment_extensions_denied: Extensions non autorisΓ©es
458 setting_sys_api_key: ClΓ© de protection de l'API
459 setting_sys_api_key: ClΓ© de protection de l'API
459 setting_lost_password: Autoriser la rΓ©initialisation par email de mot de passe perdu
460 setting_lost_password: Autoriser la rΓ©initialisation par email de mot de passe perdu
460 setting_new_item_menu_tab: Onglet de crΓ©ation d'objets dans le menu du project
461 setting_new_item_menu_tab: Onglet de crΓ©ation d'objets dans le menu du project
461
462
462 permission_add_project: CrΓ©er un projet
463 permission_add_project: CrΓ©er un projet
463 permission_add_subprojects: CrΓ©er des sous-projets
464 permission_add_subprojects: CrΓ©er des sous-projets
464 permission_edit_project: Modifier le projet
465 permission_edit_project: Modifier le projet
465 permission_close_project: Fermer / rΓ©ouvrir le projet
466 permission_close_project: Fermer / rΓ©ouvrir le projet
466 permission_select_project_modules: Choisir les modules
467 permission_select_project_modules: Choisir les modules
467 permission_manage_members: GΓ©rer les membres
468 permission_manage_members: GΓ©rer les membres
468 permission_manage_project_activities: GΓ©rer les activitΓ©s
469 permission_manage_project_activities: GΓ©rer les activitΓ©s
469 permission_manage_versions: GΓ©rer les versions
470 permission_manage_versions: GΓ©rer les versions
470 permission_manage_categories: GΓ©rer les catΓ©gories de demandes
471 permission_manage_categories: GΓ©rer les catΓ©gories de demandes
471 permission_view_issues: Voir les demandes
472 permission_view_issues: Voir les demandes
472 permission_add_issues: CrΓ©er des demandes
473 permission_add_issues: CrΓ©er des demandes
473 permission_edit_issues: Modifier les demandes
474 permission_edit_issues: Modifier les demandes
474 permission_copy_issues: Copier les demandes
475 permission_copy_issues: Copier les demandes
475 permission_manage_issue_relations: GΓ©rer les relations
476 permission_manage_issue_relations: GΓ©rer les relations
476 permission_set_issues_private: Rendre les demandes publiques ou privΓ©es
477 permission_set_issues_private: Rendre les demandes publiques ou privΓ©es
477 permission_set_own_issues_private: Rendre ses propres demandes publiques ou privΓ©es
478 permission_set_own_issues_private: Rendre ses propres demandes publiques ou privΓ©es
478 permission_add_issue_notes: Ajouter des notes
479 permission_add_issue_notes: Ajouter des notes
479 permission_edit_issue_notes: Modifier les notes
480 permission_edit_issue_notes: Modifier les notes
480 permission_edit_own_issue_notes: Modifier ses propres notes
481 permission_edit_own_issue_notes: Modifier ses propres notes
481 permission_view_private_notes: Voir les notes privΓ©es
482 permission_view_private_notes: Voir les notes privΓ©es
482 permission_set_notes_private: Rendre les notes privΓ©es
483 permission_set_notes_private: Rendre les notes privΓ©es
483 permission_move_issues: DΓ©placer les demandes
484 permission_move_issues: DΓ©placer les demandes
484 permission_delete_issues: Supprimer les demandes
485 permission_delete_issues: Supprimer les demandes
485 permission_manage_public_queries: GΓ©rer les requΓͺtes publiques
486 permission_manage_public_queries: GΓ©rer les requΓͺtes publiques
486 permission_save_queries: Sauvegarder les requΓͺtes
487 permission_save_queries: Sauvegarder les requΓͺtes
487 permission_view_gantt: Voir le gantt
488 permission_view_gantt: Voir le gantt
488 permission_view_calendar: Voir le calendrier
489 permission_view_calendar: Voir le calendrier
489 permission_view_issue_watchers: Voir la liste des observateurs
490 permission_view_issue_watchers: Voir la liste des observateurs
490 permission_add_issue_watchers: Ajouter des observateurs
491 permission_add_issue_watchers: Ajouter des observateurs
491 permission_delete_issue_watchers: Supprimer des observateurs
492 permission_delete_issue_watchers: Supprimer des observateurs
492 permission_log_time: Saisir le temps passΓ©
493 permission_log_time: Saisir le temps passΓ©
493 permission_view_time_entries: Voir le temps passΓ©
494 permission_view_time_entries: Voir le temps passΓ©
494 permission_edit_time_entries: Modifier les temps passΓ©s
495 permission_edit_time_entries: Modifier les temps passΓ©s
495 permission_edit_own_time_entries: Modifier son propre temps passΓ©
496 permission_edit_own_time_entries: Modifier son propre temps passΓ©
496 permission_manage_news: GΓ©rer les annonces
497 permission_manage_news: GΓ©rer les annonces
497 permission_comment_news: Commenter les annonces
498 permission_comment_news: Commenter les annonces
498 permission_view_documents: Voir les documents
499 permission_view_documents: Voir les documents
499 permission_add_documents: Ajouter des documents
500 permission_add_documents: Ajouter des documents
500 permission_edit_documents: Modifier les documents
501 permission_edit_documents: Modifier les documents
501 permission_delete_documents: Supprimer les documents
502 permission_delete_documents: Supprimer les documents
502 permission_manage_files: GΓ©rer les fichiers
503 permission_manage_files: GΓ©rer les fichiers
503 permission_view_files: Voir les fichiers
504 permission_view_files: Voir les fichiers
504 permission_manage_wiki: GΓ©rer le wiki
505 permission_manage_wiki: GΓ©rer le wiki
505 permission_rename_wiki_pages: Renommer les pages
506 permission_rename_wiki_pages: Renommer les pages
506 permission_delete_wiki_pages: Supprimer les pages
507 permission_delete_wiki_pages: Supprimer les pages
507 permission_view_wiki_pages: Voir le wiki
508 permission_view_wiki_pages: Voir le wiki
508 permission_view_wiki_edits: "Voir l'historique des modifications"
509 permission_view_wiki_edits: "Voir l'historique des modifications"
509 permission_edit_wiki_pages: Modifier les pages
510 permission_edit_wiki_pages: Modifier les pages
510 permission_delete_wiki_pages_attachments: Supprimer les fichiers joints
511 permission_delete_wiki_pages_attachments: Supprimer les fichiers joints
511 permission_protect_wiki_pages: ProtΓ©ger les pages
512 permission_protect_wiki_pages: ProtΓ©ger les pages
512 permission_manage_repository: GΓ©rer le dΓ©pΓ΄t de sources
513 permission_manage_repository: GΓ©rer le dΓ©pΓ΄t de sources
513 permission_browse_repository: Parcourir les sources
514 permission_browse_repository: Parcourir les sources
514 permission_view_changesets: Voir les rΓ©visions
515 permission_view_changesets: Voir les rΓ©visions
515 permission_commit_access: Droit de commit
516 permission_commit_access: Droit de commit
516 permission_manage_boards: GΓ©rer les forums
517 permission_manage_boards: GΓ©rer les forums
517 permission_view_messages: Voir les messages
518 permission_view_messages: Voir les messages
518 permission_add_messages: Poster un message
519 permission_add_messages: Poster un message
519 permission_edit_messages: Modifier les messages
520 permission_edit_messages: Modifier les messages
520 permission_edit_own_messages: Modifier ses propres messages
521 permission_edit_own_messages: Modifier ses propres messages
521 permission_delete_messages: Supprimer les messages
522 permission_delete_messages: Supprimer les messages
522 permission_delete_own_messages: Supprimer ses propres messages
523 permission_delete_own_messages: Supprimer ses propres messages
523 permission_export_wiki_pages: Exporter les pages
524 permission_export_wiki_pages: Exporter les pages
524 permission_manage_subtasks: GΓ©rer les sous-tΓ’ches
525 permission_manage_subtasks: GΓ©rer les sous-tΓ’ches
525 permission_manage_related_issues: GΓ©rer les demandes associΓ©es
526 permission_manage_related_issues: GΓ©rer les demandes associΓ©es
526 permission_import_issues: Importer des demandes
527 permission_import_issues: Importer des demandes
527
528
528 project_module_issue_tracking: Suivi des demandes
529 project_module_issue_tracking: Suivi des demandes
529 project_module_time_tracking: Suivi du temps passΓ©
530 project_module_time_tracking: Suivi du temps passΓ©
530 project_module_news: Publication d'annonces
531 project_module_news: Publication d'annonces
531 project_module_documents: Publication de documents
532 project_module_documents: Publication de documents
532 project_module_files: Publication de fichiers
533 project_module_files: Publication de fichiers
533 project_module_wiki: Wiki
534 project_module_wiki: Wiki
534 project_module_repository: DΓ©pΓ΄t de sources
535 project_module_repository: DΓ©pΓ΄t de sources
535 project_module_boards: Forums de discussion
536 project_module_boards: Forums de discussion
536 project_module_calendar: Calendrier
537 project_module_calendar: Calendrier
537 project_module_gantt: Gantt
538 project_module_gantt: Gantt
538
539
539 label_user: Utilisateur
540 label_user: Utilisateur
540 label_user_plural: Utilisateurs
541 label_user_plural: Utilisateurs
541 label_user_new: Nouvel utilisateur
542 label_user_new: Nouvel utilisateur
542 label_user_anonymous: Anonyme
543 label_user_anonymous: Anonyme
543 label_project: Projet
544 label_project: Projet
544 label_project_new: Nouveau projet
545 label_project_new: Nouveau projet
545 label_project_plural: Projets
546 label_project_plural: Projets
546 label_x_projects:
547 label_x_projects:
547 zero: aucun projet
548 zero: aucun projet
548 one: un projet
549 one: un projet
549 other: "%{count} projets"
550 other: "%{count} projets"
550 label_project_all: Tous les projets
551 label_project_all: Tous les projets
551 label_project_latest: Derniers projets
552 label_project_latest: Derniers projets
552 label_issue: Demande
553 label_issue: Demande
553 label_issue_new: Nouvelle demande
554 label_issue_new: Nouvelle demande
554 label_issue_plural: Demandes
555 label_issue_plural: Demandes
555 label_issue_view_all: Voir toutes les demandes
556 label_issue_view_all: Voir toutes les demandes
556 label_issues_by: "Demandes par %{value}"
557 label_issues_by: "Demandes par %{value}"
557 label_issue_added: Demande ajoutΓ©e
558 label_issue_added: Demande ajoutΓ©e
558 label_issue_updated: Demande mise Γ  jour
559 label_issue_updated: Demande mise Γ  jour
559 label_issue_note_added: Note ajoutΓ©e
560 label_issue_note_added: Note ajoutΓ©e
560 label_issue_status_updated: Statut changΓ©
561 label_issue_status_updated: Statut changΓ©
561 label_issue_assigned_to_updated: AssignΓ© changΓ©
562 label_issue_assigned_to_updated: AssignΓ© changΓ©
562 label_issue_priority_updated: PrioritΓ© changΓ©e
563 label_issue_priority_updated: PrioritΓ© changΓ©e
563 label_document: Document
564 label_document: Document
564 label_document_new: Nouveau document
565 label_document_new: Nouveau document
565 label_document_plural: Documents
566 label_document_plural: Documents
566 label_document_added: Document ajoutΓ©
567 label_document_added: Document ajoutΓ©
567 label_role: RΓ΄le
568 label_role: RΓ΄le
568 label_role_plural: RΓ΄les
569 label_role_plural: RΓ΄les
569 label_role_new: Nouveau rΓ΄le
570 label_role_new: Nouveau rΓ΄le
570 label_role_and_permissions: RΓ΄les et permissions
571 label_role_and_permissions: RΓ΄les et permissions
571 label_role_anonymous: Anonyme
572 label_role_anonymous: Anonyme
572 label_role_non_member: Non membre
573 label_role_non_member: Non membre
573 label_member: Membre
574 label_member: Membre
574 label_member_new: Nouveau membre
575 label_member_new: Nouveau membre
575 label_member_plural: Membres
576 label_member_plural: Membres
576 label_tracker: Tracker
577 label_tracker: Tracker
577 label_tracker_plural: Trackers
578 label_tracker_plural: Trackers
578 label_tracker_all: Tous les trackers
579 label_tracker_all: Tous les trackers
579 label_tracker_new: Nouveau tracker
580 label_tracker_new: Nouveau tracker
580 label_workflow: Workflow
581 label_workflow: Workflow
581 label_issue_status: Statut de demandes
582 label_issue_status: Statut de demandes
582 label_issue_status_plural: Statuts de demandes
583 label_issue_status_plural: Statuts de demandes
583 label_issue_status_new: Nouveau statut
584 label_issue_status_new: Nouveau statut
584 label_issue_category: CatΓ©gorie de demandes
585 label_issue_category: CatΓ©gorie de demandes
585 label_issue_category_plural: CatΓ©gories de demandes
586 label_issue_category_plural: CatΓ©gories de demandes
586 label_issue_category_new: Nouvelle catΓ©gorie
587 label_issue_category_new: Nouvelle catΓ©gorie
587 label_custom_field: Champ personnalisΓ©
588 label_custom_field: Champ personnalisΓ©
588 label_custom_field_plural: Champs personnalisΓ©s
589 label_custom_field_plural: Champs personnalisΓ©s
589 label_custom_field_new: Nouveau champ personnalisΓ©
590 label_custom_field_new: Nouveau champ personnalisΓ©
590 label_enumerations: Listes de valeurs
591 label_enumerations: Listes de valeurs
591 label_enumeration_new: Nouvelle valeur
592 label_enumeration_new: Nouvelle valeur
592 label_information: Information
593 label_information: Information
593 label_information_plural: Informations
594 label_information_plural: Informations
594 label_please_login: Identification
595 label_please_login: Identification
595 label_register: S'enregistrer
596 label_register: S'enregistrer
596 label_login_with_open_id_option: S'authentifier avec OpenID
597 label_login_with_open_id_option: S'authentifier avec OpenID
597 label_password_lost: Mot de passe perdu
598 label_password_lost: Mot de passe perdu
598 label_password_required: Confirmez votre mot de passe pour continuer
599 label_password_required: Confirmez votre mot de passe pour continuer
599 label_home: Accueil
600 label_home: Accueil
600 label_my_page: Ma page
601 label_my_page: Ma page
601 label_my_account: Mon compte
602 label_my_account: Mon compte
602 label_my_projects: Mes projets
603 label_my_projects: Mes projets
603 label_my_page_block: Blocs disponibles
604 label_my_page_block: Blocs disponibles
604 label_administration: Administration
605 label_administration: Administration
605 label_login: Connexion
606 label_login: Connexion
606 label_logout: DΓ©connexion
607 label_logout: DΓ©connexion
607 label_help: Aide
608 label_help: Aide
608 label_reported_issues: Demandes soumises
609 label_reported_issues: Demandes soumises
609 label_assigned_issues: Demandes assignΓ©es
610 label_assigned_issues: Demandes assignΓ©es
610 label_assigned_to_me_issues: Demandes qui me sont assignΓ©es
611 label_assigned_to_me_issues: Demandes qui me sont assignΓ©es
611 label_last_login: Dernière connexion
612 label_last_login: Dernière connexion
612 label_registered_on: Inscrit le
613 label_registered_on: Inscrit le
613 label_activity: ActivitΓ©
614 label_activity: ActivitΓ©
614 label_overall_activity: ActivitΓ© globale
615 label_overall_activity: ActivitΓ© globale
615 label_user_activity: "ActivitΓ© de %{value}"
616 label_user_activity: "ActivitΓ© de %{value}"
616 label_new: Nouveau
617 label_new: Nouveau
617 label_logged_as: ConnectΓ© en tant que
618 label_logged_as: ConnectΓ© en tant que
618 label_environment: Environnement
619 label_environment: Environnement
619 label_authentication: Authentification
620 label_authentication: Authentification
620 label_auth_source: Mode d'authentification
621 label_auth_source: Mode d'authentification
621 label_auth_source_new: Nouveau mode d'authentification
622 label_auth_source_new: Nouveau mode d'authentification
622 label_auth_source_plural: Modes d'authentification
623 label_auth_source_plural: Modes d'authentification
623 label_subproject_plural: Sous-projets
624 label_subproject_plural: Sous-projets
624 label_subproject_new: Nouveau sous-projet
625 label_subproject_new: Nouveau sous-projet
625 label_and_its_subprojects: "%{value} et ses sous-projets"
626 label_and_its_subprojects: "%{value} et ses sous-projets"
626 label_min_max_length: Longueurs mini - maxi
627 label_min_max_length: Longueurs mini - maxi
627 label_list: Liste
628 label_list: Liste
628 label_date: Date
629 label_date: Date
629 label_integer: Entier
630 label_integer: Entier
630 label_float: Nombre dΓ©cimal
631 label_float: Nombre dΓ©cimal
631 label_boolean: BoolΓ©en
632 label_boolean: BoolΓ©en
632 label_string: Texte
633 label_string: Texte
633 label_text: Texte long
634 label_text: Texte long
634 label_attribute: Attribut
635 label_attribute: Attribut
635 label_attribute_plural: Attributs
636 label_attribute_plural: Attributs
636 label_no_data: Aucune donnΓ©e Γ  afficher
637 label_no_data: Aucune donnΓ©e Γ  afficher
637 label_change_status: Changer le statut
638 label_change_status: Changer le statut
638 label_history: Historique
639 label_history: Historique
639 label_attachment: Fichier
640 label_attachment: Fichier
640 label_attachment_new: Nouveau fichier
641 label_attachment_new: Nouveau fichier
641 label_attachment_delete: Supprimer le fichier
642 label_attachment_delete: Supprimer le fichier
642 label_attachment_plural: Fichiers
643 label_attachment_plural: Fichiers
643 label_file_added: Fichier ajoutΓ©
644 label_file_added: Fichier ajoutΓ©
644 label_report: Rapport
645 label_report: Rapport
645 label_report_plural: Rapports
646 label_report_plural: Rapports
646 label_news: Annonce
647 label_news: Annonce
647 label_news_new: Nouvelle annonce
648 label_news_new: Nouvelle annonce
648 label_news_plural: Annonces
649 label_news_plural: Annonces
649 label_news_latest: Dernières annonces
650 label_news_latest: Dernières annonces
650 label_news_view_all: Voir toutes les annonces
651 label_news_view_all: Voir toutes les annonces
651 label_news_added: Annonce ajoutΓ©e
652 label_news_added: Annonce ajoutΓ©e
652 label_news_comment_added: Commentaire ajoutΓ© Γ  une annonce
653 label_news_comment_added: Commentaire ajoutΓ© Γ  une annonce
653 label_settings: Configuration
654 label_settings: Configuration
654 label_overview: AperΓ§u
655 label_overview: AperΓ§u
655 label_version: Version
656 label_version: Version
656 label_version_new: Nouvelle version
657 label_version_new: Nouvelle version
657 label_version_plural: Versions
658 label_version_plural: Versions
658 label_close_versions: Fermer les versions terminΓ©es
659 label_close_versions: Fermer les versions terminΓ©es
659 label_confirmation: Confirmation
660 label_confirmation: Confirmation
660 label_export_to: 'Formats disponibles :'
661 label_export_to: 'Formats disponibles :'
661 label_read: Lire...
662 label_read: Lire...
662 label_public_projects: Projets publics
663 label_public_projects: Projets publics
663 label_open_issues: ouvert
664 label_open_issues: ouvert
664 label_open_issues_plural: ouverts
665 label_open_issues_plural: ouverts
665 label_closed_issues: fermΓ©
666 label_closed_issues: fermΓ©
666 label_closed_issues_plural: fermΓ©s
667 label_closed_issues_plural: fermΓ©s
667 label_x_open_issues_abbr:
668 label_x_open_issues_abbr:
668 zero: 0 ouverte
669 zero: 0 ouverte
669 one: 1 ouverte
670 one: 1 ouverte
670 other: "%{count} ouvertes"
671 other: "%{count} ouvertes"
671 label_x_closed_issues_abbr:
672 label_x_closed_issues_abbr:
672 zero: 0 fermΓ©e
673 zero: 0 fermΓ©e
673 one: 1 fermΓ©e
674 one: 1 fermΓ©e
674 other: "%{count} fermΓ©es"
675 other: "%{count} fermΓ©es"
675 label_x_issues:
676 label_x_issues:
676 zero: 0 demande
677 zero: 0 demande
677 one: 1 demande
678 one: 1 demande
678 other: "%{count} demandes"
679 other: "%{count} demandes"
679 label_total: Total
680 label_total: Total
680 label_total_plural: Totaux
681 label_total_plural: Totaux
681 label_total_time: Temps total
682 label_total_time: Temps total
682 label_permissions: Permissions
683 label_permissions: Permissions
683 label_current_status: Statut actuel
684 label_current_status: Statut actuel
684 label_new_statuses_allowed: Nouveaux statuts autorisΓ©s
685 label_new_statuses_allowed: Nouveaux statuts autorisΓ©s
685 label_all: tous
686 label_all: tous
686 label_any: tous
687 label_any: tous
687 label_none: aucun
688 label_none: aucun
688 label_nobody: personne
689 label_nobody: personne
689 label_next: Suivant
690 label_next: Suivant
690 label_previous: PrΓ©cΓ©dent
691 label_previous: PrΓ©cΓ©dent
691 label_used_by: UtilisΓ© par
692 label_used_by: UtilisΓ© par
692 label_details: DΓ©tails
693 label_details: DΓ©tails
693 label_add_note: Ajouter une note
694 label_add_note: Ajouter une note
694 label_calendar: Calendrier
695 label_calendar: Calendrier
695 label_months_from: mois depuis
696 label_months_from: mois depuis
696 label_gantt: Gantt
697 label_gantt: Gantt
697 label_internal: Interne
698 label_internal: Interne
698 label_last_changes: "%{count} derniers changements"
699 label_last_changes: "%{count} derniers changements"
699 label_change_view_all: Voir tous les changements
700 label_change_view_all: Voir tous les changements
700 label_personalize_page: Personnaliser cette page
701 label_personalize_page: Personnaliser cette page
701 label_comment: Commentaire
702 label_comment: Commentaire
702 label_comment_plural: Commentaires
703 label_comment_plural: Commentaires
703 label_x_comments:
704 label_x_comments:
704 zero: aucun commentaire
705 zero: aucun commentaire
705 one: un commentaire
706 one: un commentaire
706 other: "%{count} commentaires"
707 other: "%{count} commentaires"
707 label_comment_add: Ajouter un commentaire
708 label_comment_add: Ajouter un commentaire
708 label_comment_added: Commentaire ajoutΓ©
709 label_comment_added: Commentaire ajoutΓ©
709 label_comment_delete: Supprimer les commentaires
710 label_comment_delete: Supprimer les commentaires
710 label_query: Rapport personnalisΓ©
711 label_query: Rapport personnalisΓ©
711 label_query_plural: Rapports personnalisΓ©s
712 label_query_plural: Rapports personnalisΓ©s
712 label_query_new: Nouveau rapport
713 label_query_new: Nouveau rapport
713 label_my_queries: Mes rapports personnalisΓ©s
714 label_my_queries: Mes rapports personnalisΓ©s
714 label_filter_add: Ajouter le filtre
715 label_filter_add: Ajouter le filtre
715 label_filter_plural: Filtres
716 label_filter_plural: Filtres
716 label_equals: Γ©gal
717 label_equals: Γ©gal
717 label_not_equals: diffΓ©rent
718 label_not_equals: diffΓ©rent
718 label_in_less_than: dans moins de
719 label_in_less_than: dans moins de
719 label_in_more_than: dans plus de
720 label_in_more_than: dans plus de
720 label_in_the_next_days: dans les prochains jours
721 label_in_the_next_days: dans les prochains jours
721 label_in_the_past_days: dans les derniers jours
722 label_in_the_past_days: dans les derniers jours
722 label_greater_or_equal: '>='
723 label_greater_or_equal: '>='
723 label_less_or_equal: '<='
724 label_less_or_equal: '<='
724 label_between: entre
725 label_between: entre
725 label_in: dans
726 label_in: dans
726 label_today: aujourd'hui
727 label_today: aujourd'hui
727 label_all_time: toute la pΓ©riode
728 label_all_time: toute la pΓ©riode
728 label_yesterday: hier
729 label_yesterday: hier
729 label_this_week: cette semaine
730 label_this_week: cette semaine
730 label_last_week: la semaine dernière
731 label_last_week: la semaine dernière
731 label_last_n_weeks: "les %{count} dernières semaines"
732 label_last_n_weeks: "les %{count} dernières semaines"
732 label_last_n_days: "les %{count} derniers jours"
733 label_last_n_days: "les %{count} derniers jours"
733 label_this_month: ce mois-ci
734 label_this_month: ce mois-ci
734 label_last_month: le mois dernier
735 label_last_month: le mois dernier
735 label_this_year: cette annΓ©e
736 label_this_year: cette annΓ©e
736 label_date_range: PΓ©riode
737 label_date_range: PΓ©riode
737 label_less_than_ago: il y a moins de
738 label_less_than_ago: il y a moins de
738 label_more_than_ago: il y a plus de
739 label_more_than_ago: il y a plus de
739 label_ago: il y a
740 label_ago: il y a
740 label_contains: contient
741 label_contains: contient
741 label_not_contains: ne contient pas
742 label_not_contains: ne contient pas
742 label_any_issues_in_project: une demande du projet
743 label_any_issues_in_project: une demande du projet
743 label_any_issues_not_in_project: une demande hors du projet
744 label_any_issues_not_in_project: une demande hors du projet
744 label_no_issues_in_project: aucune demande du projet
745 label_no_issues_in_project: aucune demande du projet
745 label_any_open_issues: une demande ouverte
746 label_any_open_issues: une demande ouverte
746 label_no_open_issues: aucune demande ouverte
747 label_no_open_issues: aucune demande ouverte
747 label_day_plural: jours
748 label_day_plural: jours
748 label_repository: DΓ©pΓ΄t
749 label_repository: DΓ©pΓ΄t
749 label_repository_new: Nouveau dΓ©pΓ΄t
750 label_repository_new: Nouveau dΓ©pΓ΄t
750 label_repository_plural: DΓ©pΓ΄ts
751 label_repository_plural: DΓ©pΓ΄ts
751 label_browse: Parcourir
752 label_browse: Parcourir
752 label_branch: Branche
753 label_branch: Branche
753 label_tag: Tag
754 label_tag: Tag
754 label_revision: RΓ©vision
755 label_revision: RΓ©vision
755 label_revision_plural: RΓ©visions
756 label_revision_plural: RΓ©visions
756 label_revision_id: "RΓ©vision %{value}"
757 label_revision_id: "RΓ©vision %{value}"
757 label_associated_revisions: RΓ©visions associΓ©es
758 label_associated_revisions: RΓ©visions associΓ©es
758 label_added: ajoutΓ©
759 label_added: ajoutΓ©
759 label_modified: modifiΓ©
760 label_modified: modifiΓ©
760 label_copied: copiΓ©
761 label_copied: copiΓ©
761 label_renamed: renommΓ©
762 label_renamed: renommΓ©
762 label_deleted: supprimΓ©
763 label_deleted: supprimΓ©
763 label_latest_revision: Dernière révision
764 label_latest_revision: Dernière révision
764 label_latest_revision_plural: Dernières révisions
765 label_latest_revision_plural: Dernières révisions
765 label_view_revisions: Voir les rΓ©visions
766 label_view_revisions: Voir les rΓ©visions
766 label_view_all_revisions: Voir toutes les rΓ©visions
767 label_view_all_revisions: Voir toutes les rΓ©visions
767 label_max_size: Taille maximale
768 label_max_size: Taille maximale
768 label_sort_highest: Remonter en premier
769 label_sort_highest: Remonter en premier
769 label_sort_higher: Remonter
770 label_sort_higher: Remonter
770 label_sort_lower: Descendre
771 label_sort_lower: Descendre
771 label_sort_lowest: Descendre en dernier
772 label_sort_lowest: Descendre en dernier
772 label_roadmap: Roadmap
773 label_roadmap: Roadmap
773 label_roadmap_due_in: "Γ‰chΓ©ance dans %{value}"
774 label_roadmap_due_in: "Γ‰chΓ©ance dans %{value}"
774 label_roadmap_overdue: "En retard de %{value}"
775 label_roadmap_overdue: "En retard de %{value}"
775 label_roadmap_no_issues: Aucune demande pour cette version
776 label_roadmap_no_issues: Aucune demande pour cette version
776 label_search: Recherche
777 label_search: Recherche
777 label_result_plural: RΓ©sultats
778 label_result_plural: RΓ©sultats
778 label_all_words: Tous les mots
779 label_all_words: Tous les mots
779 label_wiki: Wiki
780 label_wiki: Wiki
780 label_wiki_edit: RΓ©vision wiki
781 label_wiki_edit: RΓ©vision wiki
781 label_wiki_edit_plural: RΓ©visions wiki
782 label_wiki_edit_plural: RΓ©visions wiki
782 label_wiki_page: Page wiki
783 label_wiki_page: Page wiki
783 label_wiki_page_plural: Pages wiki
784 label_wiki_page_plural: Pages wiki
784 label_wiki_page_new: Nouvelle page wiki
785 label_wiki_page_new: Nouvelle page wiki
785 label_index_by_title: Index par titre
786 label_index_by_title: Index par titre
786 label_index_by_date: Index par date
787 label_index_by_date: Index par date
787 label_current_version: Version actuelle
788 label_current_version: Version actuelle
788 label_preview: PrΓ©visualisation
789 label_preview: PrΓ©visualisation
789 label_feed_plural: Flux Atom
790 label_feed_plural: Flux Atom
790 label_changes_details: DΓ©tails de tous les changements
791 label_changes_details: DΓ©tails de tous les changements
791 label_issue_tracking: Suivi des demandes
792 label_issue_tracking: Suivi des demandes
792 label_spent_time: Temps passΓ©
793 label_spent_time: Temps passΓ©
793 label_total_spent_time: Temps passΓ© total
794 label_total_spent_time: Temps passΓ© total
794 label_overall_spent_time: Temps passΓ© global
795 label_overall_spent_time: Temps passΓ© global
795 label_f_hour: "%{value} heure"
796 label_f_hour: "%{value} heure"
796 label_f_hour_plural: "%{value} heures"
797 label_f_hour_plural: "%{value} heures"
797 label_f_hour_short: "%{value} h"
798 label_f_hour_short: "%{value} h"
798 label_time_tracking: Suivi du temps
799 label_time_tracking: Suivi du temps
799 label_change_plural: Changements
800 label_change_plural: Changements
800 label_statistics: Statistiques
801 label_statistics: Statistiques
801 label_commits_per_month: Commits par mois
802 label_commits_per_month: Commits par mois
802 label_commits_per_author: Commits par auteur
803 label_commits_per_author: Commits par auteur
803 label_diff: diff
804 label_diff: diff
804 label_view_diff: Voir les diffΓ©rences
805 label_view_diff: Voir les diffΓ©rences
805 label_diff_inline: en ligne
806 label_diff_inline: en ligne
806 label_diff_side_by_side: cΓ΄te Γ  cΓ΄te
807 label_diff_side_by_side: cΓ΄te Γ  cΓ΄te
807 label_options: Options
808 label_options: Options
808 label_copy_workflow_from: Copier le workflow de
809 label_copy_workflow_from: Copier le workflow de
809 label_permissions_report: Synthèse des permissions
810 label_permissions_report: Synthèse des permissions
810 label_watched_issues: Demandes surveillΓ©es
811 label_watched_issues: Demandes surveillΓ©es
811 label_related_issues: Demandes liΓ©es
812 label_related_issues: Demandes liΓ©es
812 label_applied_status: Statut appliquΓ©
813 label_applied_status: Statut appliquΓ©
813 label_loading: Chargement...
814 label_loading: Chargement...
814 label_relation_new: Nouvelle relation
815 label_relation_new: Nouvelle relation
815 label_relation_delete: Supprimer la relation
816 label_relation_delete: Supprimer la relation
816 label_relates_to: LiΓ© Γ 
817 label_relates_to: LiΓ© Γ 
817 label_duplicates: Duplique
818 label_duplicates: Duplique
818 label_duplicated_by: DupliquΓ© par
819 label_duplicated_by: DupliquΓ© par
819 label_blocks: Bloque
820 label_blocks: Bloque
820 label_blocked_by: BloquΓ© par
821 label_blocked_by: BloquΓ© par
821 label_precedes: Précède
822 label_precedes: Précède
822 label_follows: Suit
823 label_follows: Suit
823 label_copied_to: CopiΓ© vers
824 label_copied_to: CopiΓ© vers
824 label_copied_from: CopiΓ© depuis
825 label_copied_from: CopiΓ© depuis
825 label_stay_logged_in: Rester connectΓ©
826 label_stay_logged_in: Rester connectΓ©
826 label_disabled: dΓ©sactivΓ©
827 label_disabled: dΓ©sactivΓ©
827 label_show_completed_versions: Voir les versions passΓ©es
828 label_show_completed_versions: Voir les versions passΓ©es
828 label_me: moi
829 label_me: moi
829 label_board: Forum
830 label_board: Forum
830 label_board_new: Nouveau forum
831 label_board_new: Nouveau forum
831 label_board_plural: Forums
832 label_board_plural: Forums
832 label_board_locked: VerrouillΓ©
833 label_board_locked: VerrouillΓ©
833 label_board_sticky: Sticky
834 label_board_sticky: Sticky
834 label_topic_plural: Discussions
835 label_topic_plural: Discussions
835 label_message_plural: Messages
836 label_message_plural: Messages
836 label_message_last: Dernier message
837 label_message_last: Dernier message
837 label_message_new: Nouveau message
838 label_message_new: Nouveau message
838 label_message_posted: Message ajoutΓ©
839 label_message_posted: Message ajoutΓ©
839 label_reply_plural: RΓ©ponses
840 label_reply_plural: RΓ©ponses
840 label_send_information: Envoyer les informations Γ  l'utilisateur
841 label_send_information: Envoyer les informations Γ  l'utilisateur
841 label_year: AnnΓ©e
842 label_year: AnnΓ©e
842 label_month: Mois
843 label_month: Mois
843 label_week: Semaine
844 label_week: Semaine
844 label_date_from: Du
845 label_date_from: Du
845 label_date_to: Au
846 label_date_to: Au
846 label_language_based: BasΓ© sur la langue de l'utilisateur
847 label_language_based: BasΓ© sur la langue de l'utilisateur
847 label_sort_by: "Trier par %{value}"
848 label_sort_by: "Trier par %{value}"
848 label_send_test_email: Envoyer un email de test
849 label_send_test_email: Envoyer un email de test
849 label_feeds_access_key: Clé d'accès Atom
850 label_feeds_access_key: Clé d'accès Atom
850 label_missing_feeds_access_key: Clé d'accès Atom manquante
851 label_missing_feeds_access_key: Clé d'accès Atom manquante
851 label_feeds_access_key_created_on: "Clé d'accès Atom créée il y a %{value}"
852 label_feeds_access_key_created_on: "Clé d'accès Atom créée il y a %{value}"
852 label_module_plural: Modules
853 label_module_plural: Modules
853 label_added_time_by: "AjoutΓ© par %{author} il y a %{age}"
854 label_added_time_by: "AjoutΓ© par %{author} il y a %{age}"
854 label_updated_time_by: "Mis Γ  jour par %{author} il y a %{age}"
855 label_updated_time_by: "Mis Γ  jour par %{author} il y a %{age}"
855 label_updated_time: "Mis Γ  jour il y a %{value}"
856 label_updated_time: "Mis Γ  jour il y a %{value}"
856 label_jump_to_a_project: Aller Γ  un projet...
857 label_jump_to_a_project: Aller Γ  un projet...
857 label_file_plural: Fichiers
858 label_file_plural: Fichiers
858 label_changeset_plural: RΓ©visions
859 label_changeset_plural: RΓ©visions
859 label_default_columns: Colonnes par dΓ©faut
860 label_default_columns: Colonnes par dΓ©faut
860 label_no_change_option: (Pas de changement)
861 label_no_change_option: (Pas de changement)
861 label_bulk_edit_selected_issues: Modifier les demandes sΓ©lectionnΓ©es
862 label_bulk_edit_selected_issues: Modifier les demandes sΓ©lectionnΓ©es
862 label_bulk_edit_selected_time_entries: Modifier les temps passΓ©s sΓ©lectionnΓ©s
863 label_bulk_edit_selected_time_entries: Modifier les temps passΓ©s sΓ©lectionnΓ©s
863 label_theme: Thème
864 label_theme: Thème
864 label_default: DΓ©faut
865 label_default: DΓ©faut
865 label_search_titles_only: Uniquement dans les titres
866 label_search_titles_only: Uniquement dans les titres
866 label_user_mail_option_all: "Pour tous les Γ©vΓ©nements de tous mes projets"
867 label_user_mail_option_all: "Pour tous les Γ©vΓ©nements de tous mes projets"
867 label_user_mail_option_selected: "Pour tous les Γ©vΓ©nements des projets sΓ©lectionnΓ©s..."
868 label_user_mail_option_selected: "Pour tous les Γ©vΓ©nements des projets sΓ©lectionnΓ©s..."
868 label_user_mail_option_none: Aucune notification
869 label_user_mail_option_none: Aucune notification
869 label_user_mail_option_only_my_events: Seulement pour ce que je surveille
870 label_user_mail_option_only_my_events: Seulement pour ce que je surveille
870 label_user_mail_option_only_assigned: Seulement pour ce qui m'est assignΓ©
871 label_user_mail_option_only_assigned: Seulement pour ce qui m'est assignΓ©
871 label_user_mail_option_only_owner: Seulement pour ce que j'ai créé
872 label_user_mail_option_only_owner: Seulement pour ce que j'ai créé
872 label_user_mail_no_self_notified: "Je ne veux pas Γͺtre notifiΓ© des changements que j'effectue"
873 label_user_mail_no_self_notified: "Je ne veux pas Γͺtre notifiΓ© des changements que j'effectue"
873 label_registration_activation_by_email: activation du compte par email
874 label_registration_activation_by_email: activation du compte par email
874 label_registration_manual_activation: activation manuelle du compte
875 label_registration_manual_activation: activation manuelle du compte
875 label_registration_automatic_activation: activation automatique du compte
876 label_registration_automatic_activation: activation automatique du compte
876 label_display_per_page: "Par page : %{value}"
877 label_display_per_page: "Par page : %{value}"
877 label_age: Γ‚ge
878 label_age: Γ‚ge
878 label_change_properties: Changer les propriΓ©tΓ©s
879 label_change_properties: Changer les propriΓ©tΓ©s
879 label_general: GΓ©nΓ©ral
880 label_general: GΓ©nΓ©ral
880 label_more: Plus
881 label_more: Plus
881 label_scm: SCM
882 label_scm: SCM
882 label_plugins: Plugins
883 label_plugins: Plugins
883 label_ldap_authentication: Authentification LDAP
884 label_ldap_authentication: Authentification LDAP
884 label_downloads_abbr: D/L
885 label_downloads_abbr: D/L
885 label_optional_description: Description facultative
886 label_optional_description: Description facultative
886 label_add_another_file: Ajouter un autre fichier
887 label_add_another_file: Ajouter un autre fichier
887 label_preferences: PrΓ©fΓ©rences
888 label_preferences: PrΓ©fΓ©rences
888 label_chronological_order: Dans l'ordre chronologique
889 label_chronological_order: Dans l'ordre chronologique
889 label_reverse_chronological_order: Dans l'ordre chronologique inverse
890 label_reverse_chronological_order: Dans l'ordre chronologique inverse
890 label_planning: Planning
891 label_planning: Planning
891 label_incoming_emails: Emails entrants
892 label_incoming_emails: Emails entrants
892 label_generate_key: GΓ©nΓ©rer une clΓ©
893 label_generate_key: GΓ©nΓ©rer une clΓ©
893 label_issue_watchers: Observateurs
894 label_issue_watchers: Observateurs
894 label_example: Exemple
895 label_example: Exemple
895 label_display: Affichage
896 label_display: Affichage
896 label_sort: Tri
897 label_sort: Tri
897 label_ascending: Croissant
898 label_ascending: Croissant
898 label_descending: DΓ©croissant
899 label_descending: DΓ©croissant
899 label_date_from_to: Du %{start} au %{end}
900 label_date_from_to: Du %{start} au %{end}
900 label_wiki_content_added: Page wiki ajoutΓ©e
901 label_wiki_content_added: Page wiki ajoutΓ©e
901 label_wiki_content_updated: Page wiki mise Γ  jour
902 label_wiki_content_updated: Page wiki mise Γ  jour
902 label_group: Groupe
903 label_group: Groupe
903 label_group_plural: Groupes
904 label_group_plural: Groupes
904 label_group_new: Nouveau groupe
905 label_group_new: Nouveau groupe
905 label_group_anonymous: Utilisateurs anonymes
906 label_group_anonymous: Utilisateurs anonymes
906 label_group_non_member: Utilisateurs non membres
907 label_group_non_member: Utilisateurs non membres
907 label_time_entry_plural: Temps passΓ©
908 label_time_entry_plural: Temps passΓ©
908 label_version_sharing_none: Non partagΓ©
909 label_version_sharing_none: Non partagΓ©
909 label_version_sharing_descendants: Avec les sous-projets
910 label_version_sharing_descendants: Avec les sous-projets
910 label_version_sharing_hierarchy: Avec toute la hiΓ©rarchie
911 label_version_sharing_hierarchy: Avec toute la hiΓ©rarchie
911 label_version_sharing_tree: Avec tout l'arbre
912 label_version_sharing_tree: Avec tout l'arbre
912 label_version_sharing_system: Avec tous les projets
913 label_version_sharing_system: Avec tous les projets
913 label_update_issue_done_ratios: Mettre Γ  jour l'avancement des demandes
914 label_update_issue_done_ratios: Mettre Γ  jour l'avancement des demandes
914 label_copy_source: Source
915 label_copy_source: Source
915 label_copy_target: Cible
916 label_copy_target: Cible
916 label_copy_same_as_target: Comme la cible
917 label_copy_same_as_target: Comme la cible
917 label_display_used_statuses_only: N'afficher que les statuts utilisΓ©s dans ce tracker
918 label_display_used_statuses_only: N'afficher que les statuts utilisΓ©s dans ce tracker
918 label_api_access_key: Clé d'accès API
919 label_api_access_key: Clé d'accès API
919 label_missing_api_access_key: Clé d'accès API manquante
920 label_missing_api_access_key: Clé d'accès API manquante
920 label_api_access_key_created_on: Clé d'accès API créée il y a %{value}
921 label_api_access_key_created_on: Clé d'accès API créée il y a %{value}
921 label_profile: Profil
922 label_profile: Profil
922 label_subtask_plural: Sous-tΓ’ches
923 label_subtask_plural: Sous-tΓ’ches
923 label_project_copy_notifications: Envoyer les notifications durant la copie du projet
924 label_project_copy_notifications: Envoyer les notifications durant la copie du projet
924 label_principal_search: "Rechercher un utilisateur ou un groupe :"
925 label_principal_search: "Rechercher un utilisateur ou un groupe :"
925 label_user_search: "Rechercher un utilisateur :"
926 label_user_search: "Rechercher un utilisateur :"
926 label_additional_workflow_transitions_for_author: Autorisations supplémentaires lorsque l'utilisateur a créé la demande
927 label_additional_workflow_transitions_for_author: Autorisations supplémentaires lorsque l'utilisateur a créé la demande
927 label_additional_workflow_transitions_for_assignee: Autorisations supplΓ©mentaires lorsque la demande est assignΓ©e Γ  l'utilisateur
928 label_additional_workflow_transitions_for_assignee: Autorisations supplΓ©mentaires lorsque la demande est assignΓ©e Γ  l'utilisateur
928 label_issues_visibility_all: Toutes les demandes
929 label_issues_visibility_all: Toutes les demandes
929 label_issues_visibility_public: Toutes les demandes non privΓ©es
930 label_issues_visibility_public: Toutes les demandes non privΓ©es
930 label_issues_visibility_own: Demandes créées par ou assignées à l'utilisateur
931 label_issues_visibility_own: Demandes créées par ou assignées à l'utilisateur
931 label_git_report_last_commit: Afficher le dernier commit des fichiers et rΓ©pertoires
932 label_git_report_last_commit: Afficher le dernier commit des fichiers et rΓ©pertoires
932 label_parent_revision: Parent
933 label_parent_revision: Parent
933 label_child_revision: Enfant
934 label_child_revision: Enfant
934 label_export_options: Options d'exportation %{export_format}
935 label_export_options: Options d'exportation %{export_format}
935 label_copy_attachments: Copier les fichiers
936 label_copy_attachments: Copier les fichiers
936 label_copy_subtasks: Copier les sous-tΓ’ches
937 label_copy_subtasks: Copier les sous-tΓ’ches
937 label_item_position: "%{position} sur %{count}"
938 label_item_position: "%{position} sur %{count}"
938 label_completed_versions: Versions passΓ©es
939 label_completed_versions: Versions passΓ©es
939 label_search_for_watchers: Rechercher des observateurs
940 label_search_for_watchers: Rechercher des observateurs
940 label_session_expiration: Expiration des sessions
941 label_session_expiration: Expiration des sessions
941 label_show_closed_projects: Voir les projets fermΓ©s
942 label_show_closed_projects: Voir les projets fermΓ©s
942 label_status_transitions: Changements de statut
943 label_status_transitions: Changements de statut
943 label_fields_permissions: Permissions sur les champs
944 label_fields_permissions: Permissions sur les champs
944 label_readonly: Lecture
945 label_readonly: Lecture
945 label_required: Obligatoire
946 label_required: Obligatoire
946 label_hidden: CachΓ©
947 label_hidden: CachΓ©
947 label_attribute_of_project: "%{name} du projet"
948 label_attribute_of_project: "%{name} du projet"
948 label_attribute_of_issue: "%{name} de la demande"
949 label_attribute_of_issue: "%{name} de la demande"
949 label_attribute_of_author: "%{name} de l'auteur"
950 label_attribute_of_author: "%{name} de l'auteur"
950 label_attribute_of_assigned_to: "%{name} de l'assignΓ©"
951 label_attribute_of_assigned_to: "%{name} de l'assignΓ©"
951 label_attribute_of_user: "%{name} de l'utilisateur"
952 label_attribute_of_user: "%{name} de l'utilisateur"
952 label_attribute_of_fixed_version: "%{name} de la version cible"
953 label_attribute_of_fixed_version: "%{name} de la version cible"
953 label_cross_project_descendants: Avec les sous-projets
954 label_cross_project_descendants: Avec les sous-projets
954 label_cross_project_tree: Avec tout l'arbre
955 label_cross_project_tree: Avec tout l'arbre
955 label_cross_project_hierarchy: Avec toute la hiΓ©rarchie
956 label_cross_project_hierarchy: Avec toute la hiΓ©rarchie
956 label_cross_project_system: Avec tous les projets
957 label_cross_project_system: Avec tous les projets
957 label_gantt_progress_line: Ligne de progression
958 label_gantt_progress_line: Ligne de progression
958 label_visibility_private: par moi uniquement
959 label_visibility_private: par moi uniquement
959 label_visibility_roles: par ces rΓ΄les uniquement
960 label_visibility_roles: par ces rΓ΄les uniquement
960 label_visibility_public: par tout le monde
961 label_visibility_public: par tout le monde
961 label_link: Lien
962 label_link: Lien
962 label_only: seulement
963 label_only: seulement
963 label_drop_down_list: liste dΓ©roulante
964 label_drop_down_list: liste dΓ©roulante
964 label_checkboxes: cases Γ  cocher
965 label_checkboxes: cases Γ  cocher
965 label_radio_buttons: boutons radio
966 label_radio_buttons: boutons radio
966 label_link_values_to: Lier les valeurs vers l'URL
967 label_link_values_to: Lier les valeurs vers l'URL
967 label_custom_field_select_type: Selectionner le type d'objet auquel attacher le champ personnalisΓ©
968 label_custom_field_select_type: Selectionner le type d'objet auquel attacher le champ personnalisΓ©
968 label_check_for_updates: VΓ©rifier les mises Γ  jour
969 label_check_for_updates: VΓ©rifier les mises Γ  jour
969 label_latest_compatible_version: Dernière version compatible
970 label_latest_compatible_version: Dernière version compatible
970 label_unknown_plugin: Plugin inconnu
971 label_unknown_plugin: Plugin inconnu
971 label_add_projects: Ajouter des projets
972 label_add_projects: Ajouter des projets
972 label_users_visibility_all: Tous les utilisateurs actifs
973 label_users_visibility_all: Tous les utilisateurs actifs
973 label_users_visibility_members_of_visible_projects: Membres des projets visibles
974 label_users_visibility_members_of_visible_projects: Membres des projets visibles
974 label_edit_attachments: Modifier les fichiers attachΓ©s
975 label_edit_attachments: Modifier les fichiers attachΓ©s
975 label_link_copied_issue: Lier la demande copiΓ©e
976 label_link_copied_issue: Lier la demande copiΓ©e
976 label_ask: Demander
977 label_ask: Demander
977 label_search_attachments_yes: Rechercher les noms et descriptions de fichiers
978 label_search_attachments_yes: Rechercher les noms et descriptions de fichiers
978 label_search_attachments_no: Ne pas rechercher les fichiers
979 label_search_attachments_no: Ne pas rechercher les fichiers
979 label_search_attachments_only: Rechercher les fichiers uniquement
980 label_search_attachments_only: Rechercher les fichiers uniquement
980 label_search_open_issues_only: Demandes ouvertes uniquement
981 label_search_open_issues_only: Demandes ouvertes uniquement
981 label_email_address_plural: Emails
982 label_email_address_plural: Emails
982 label_email_address_add: Ajouter une adresse email
983 label_email_address_add: Ajouter une adresse email
983 label_enable_notifications: Activer les notifications
984 label_enable_notifications: Activer les notifications
984 label_disable_notifications: DΓ©sactiver les notifications
985 label_disable_notifications: DΓ©sactiver les notifications
985 label_blank_value: non renseignΓ©
986 label_blank_value: non renseignΓ©
986 label_parent_task_attributes: Attributs des tΓ’ches parentes
987 label_parent_task_attributes: Attributs des tΓ’ches parentes
987 label_time_entries_visibility_all: Tous les temps passΓ©s
988 label_time_entries_visibility_all: Tous les temps passΓ©s
988 label_time_entries_visibility_own: Ses propres temps passΓ©s
989 label_time_entries_visibility_own: Ses propres temps passΓ©s
989 label_member_management: Gestion des membres
990 label_member_management: Gestion des membres
990 label_member_management_all_roles: Tous les rΓ΄les
991 label_member_management_all_roles: Tous les rΓ΄les
991 label_member_management_selected_roles_only: Ces rΓ΄les uniquement
992 label_member_management_selected_roles_only: Ces rΓ΄les uniquement
992 label_import_issues: Importer des demandes
993 label_import_issues: Importer des demandes
993 label_select_file_to_import: SΓ©lectionner le fichier Γ  importer
994 label_select_file_to_import: SΓ©lectionner le fichier Γ  importer
994 label_fields_separator: SΓ©parateur de champs
995 label_fields_separator: SΓ©parateur de champs
995 label_fields_wrapper: DΓ©limiteur de texte
996 label_fields_wrapper: DΓ©limiteur de texte
996 label_encoding: Encodage
997 label_encoding: Encodage
997 label_comma_char: Virgule
998 label_comma_char: Virgule
998 label_semi_colon_char: Point virgule
999 label_semi_colon_char: Point virgule
999 label_quote_char: Apostrophe
1000 label_quote_char: Apostrophe
1000 label_double_quote_char: Double apostrophe
1001 label_double_quote_char: Double apostrophe
1001 label_fields_mapping: Correspondance des champs
1002 label_fields_mapping: Correspondance des champs
1002 label_file_content_preview: AperΓ§u du contenu du fichier
1003 label_file_content_preview: AperΓ§u du contenu du fichier
1003 label_create_missing_values: CrΓ©er les valeurs manquantes
1004 label_create_missing_values: CrΓ©er les valeurs manquantes
1004 label_api: API
1005 label_api: API
1005 label_field_format_enumeration: Liste clΓ©/valeur
1006 label_field_format_enumeration: Liste clΓ©/valeur
1006 label_default_values_for_new_users: Valeurs par dΓ©faut pour les nouveaux utilisateurs
1007 label_default_values_for_new_users: Valeurs par dΓ©faut pour les nouveaux utilisateurs
1007 label_relations: Relations
1008 label_relations: Relations
1008 label_new_project_issue_tab_enabled: Afficher l'onglet "Nouvelle demande"
1009 label_new_project_issue_tab_enabled: Afficher l'onglet "Nouvelle demande"
1009 label_new_object_tab_enabled: Afficher le menu dΓ©roulant "+"
1010 label_new_object_tab_enabled: Afficher le menu dΓ©roulant "+"
1011 label_font_default: Police par dΓ©faut
1012 label_font_monospace: Police non proportionnelle
1013 label_font_proportional: Police proportionnelle
1010
1014
1011 button_login: Connexion
1015 button_login: Connexion
1012 button_submit: Soumettre
1016 button_submit: Soumettre
1013 button_save: Sauvegarder
1017 button_save: Sauvegarder
1014 button_check_all: Tout cocher
1018 button_check_all: Tout cocher
1015 button_uncheck_all: Tout dΓ©cocher
1019 button_uncheck_all: Tout dΓ©cocher
1016 button_collapse_all: Plier tout
1020 button_collapse_all: Plier tout
1017 button_expand_all: DΓ©plier tout
1021 button_expand_all: DΓ©plier tout
1018 button_delete: Supprimer
1022 button_delete: Supprimer
1019 button_create: CrΓ©er
1023 button_create: CrΓ©er
1020 button_create_and_continue: CrΓ©er et continuer
1024 button_create_and_continue: CrΓ©er et continuer
1021 button_test: Tester
1025 button_test: Tester
1022 button_edit: Modifier
1026 button_edit: Modifier
1023 button_edit_associated_wikipage: "Modifier la page wiki associΓ©e: %{page_title}"
1027 button_edit_associated_wikipage: "Modifier la page wiki associΓ©e: %{page_title}"
1024 button_add: Ajouter
1028 button_add: Ajouter
1025 button_change: Changer
1029 button_change: Changer
1026 button_apply: Appliquer
1030 button_apply: Appliquer
1027 button_clear: Effacer
1031 button_clear: Effacer
1028 button_lock: Verrouiller
1032 button_lock: Verrouiller
1029 button_unlock: DΓ©verrouiller
1033 button_unlock: DΓ©verrouiller
1030 button_download: TΓ©lΓ©charger
1034 button_download: TΓ©lΓ©charger
1031 button_list: Lister
1035 button_list: Lister
1032 button_view: Voir
1036 button_view: Voir
1033 button_move: DΓ©placer
1037 button_move: DΓ©placer
1034 button_move_and_follow: DΓ©placer et suivre
1038 button_move_and_follow: DΓ©placer et suivre
1035 button_back: Retour
1039 button_back: Retour
1036 button_cancel: Annuler
1040 button_cancel: Annuler
1037 button_activate: Activer
1041 button_activate: Activer
1038 button_sort: Trier
1042 button_sort: Trier
1039 button_log_time: Saisir temps
1043 button_log_time: Saisir temps
1040 button_rollback: Revenir Γ  cette version
1044 button_rollback: Revenir Γ  cette version
1041 button_watch: Surveiller
1045 button_watch: Surveiller
1042 button_unwatch: Ne plus surveiller
1046 button_unwatch: Ne plus surveiller
1043 button_reply: RΓ©pondre
1047 button_reply: RΓ©pondre
1044 button_archive: Archiver
1048 button_archive: Archiver
1045 button_unarchive: DΓ©sarchiver
1049 button_unarchive: DΓ©sarchiver
1046 button_reset: RΓ©initialiser
1050 button_reset: RΓ©initialiser
1047 button_rename: Renommer
1051 button_rename: Renommer
1048 button_change_password: Changer de mot de passe
1052 button_change_password: Changer de mot de passe
1049 button_copy: Copier
1053 button_copy: Copier
1050 button_copy_and_follow: Copier et suivre
1054 button_copy_and_follow: Copier et suivre
1051 button_annotate: Annoter
1055 button_annotate: Annoter
1052 button_update: Mettre Γ  jour
1056 button_update: Mettre Γ  jour
1053 button_configure: Configurer
1057 button_configure: Configurer
1054 button_quote: Citer
1058 button_quote: Citer
1055 button_duplicate: Dupliquer
1059 button_duplicate: Dupliquer
1056 button_show: Afficher
1060 button_show: Afficher
1057 button_hide: Cacher
1061 button_hide: Cacher
1058 button_edit_section: Modifier cette section
1062 button_edit_section: Modifier cette section
1059 button_export: Exporter
1063 button_export: Exporter
1060 button_delete_my_account: Supprimer mon compte
1064 button_delete_my_account: Supprimer mon compte
1061 button_close: Fermer
1065 button_close: Fermer
1062 button_reopen: RΓ©ouvrir
1066 button_reopen: RΓ©ouvrir
1063 button_import: Importer
1067 button_import: Importer
1064 button_filter: Filtrer
1068 button_filter: Filtrer
1065
1069
1066 status_active: actif
1070 status_active: actif
1067 status_registered: enregistrΓ©
1071 status_registered: enregistrΓ©
1068 status_locked: verrouillΓ©
1072 status_locked: verrouillΓ©
1069
1073
1070 project_status_active: actif
1074 project_status_active: actif
1071 project_status_closed: fermΓ©
1075 project_status_closed: fermΓ©
1072 project_status_archived: archivΓ©
1076 project_status_archived: archivΓ©
1073
1077
1074 version_status_open: ouvert
1078 version_status_open: ouvert
1075 version_status_locked: verrouillΓ©
1079 version_status_locked: verrouillΓ©
1076 version_status_closed: fermΓ©
1080 version_status_closed: fermΓ©
1077
1081
1078 field_active: Actif
1082 field_active: Actif
1079
1083
1080 text_select_mail_notifications: Actions pour lesquelles une notification par e-mail est envoyΓ©e
1084 text_select_mail_notifications: Actions pour lesquelles une notification par e-mail est envoyΓ©e
1081 text_regexp_info: ex. ^[A-Z0-9]+$
1085 text_regexp_info: ex. ^[A-Z0-9]+$
1082 text_min_max_length_info: 0 pour aucune restriction
1086 text_min_max_length_info: 0 pour aucune restriction
1083 text_project_destroy_confirmation: Êtes-vous sûr de vouloir supprimer ce projet et toutes ses données ?
1087 text_project_destroy_confirmation: Êtes-vous sûr de vouloir supprimer ce projet et toutes ses données ?
1084 text_subprojects_destroy_warning: "Ses sous-projets : %{value} seront Γ©galement supprimΓ©s."
1088 text_subprojects_destroy_warning: "Ses sous-projets : %{value} seront Γ©galement supprimΓ©s."
1085 text_workflow_edit: SΓ©lectionner un tracker et un rΓ΄le pour Γ©diter le workflow
1089 text_workflow_edit: SΓ©lectionner un tracker et un rΓ΄le pour Γ©diter le workflow
1086 text_are_you_sure: Êtes-vous sûr ?
1090 text_are_you_sure: Êtes-vous sûr ?
1087 text_journal_changed: "%{label} changΓ© de %{old} Γ  %{new}"
1091 text_journal_changed: "%{label} changΓ© de %{old} Γ  %{new}"
1088 text_journal_changed_no_detail: "%{label} mis Γ  jour"
1092 text_journal_changed_no_detail: "%{label} mis Γ  jour"
1089 text_journal_set_to: "%{label} mis Γ  %{value}"
1093 text_journal_set_to: "%{label} mis Γ  %{value}"
1090 text_journal_deleted: "%{label} %{old} supprimΓ©"
1094 text_journal_deleted: "%{label} %{old} supprimΓ©"
1091 text_journal_added: "%{label} %{value} ajoutΓ©"
1095 text_journal_added: "%{label} %{value} ajoutΓ©"
1092 text_tip_issue_begin_day: tΓ’che commenΓ§ant ce jour
1096 text_tip_issue_begin_day: tΓ’che commenΓ§ant ce jour
1093 text_tip_issue_end_day: tΓ’che finissant ce jour
1097 text_tip_issue_end_day: tΓ’che finissant ce jour
1094 text_tip_issue_begin_end_day: tΓ’che commenΓ§ant et finissant ce jour
1098 text_tip_issue_begin_end_day: tΓ’che commenΓ§ant et finissant ce jour
1095 text_project_identifier_info: 'Seuls les lettres minuscules (a-z), chiffres, tirets et tirets bas sont autorisΓ©s, doit commencer par une minuscule.<br />Un fois sauvegardΓ©, l''identifiant ne pourra plus Γͺtre modifiΓ©.'
1099 text_project_identifier_info: 'Seuls les lettres minuscules (a-z), chiffres, tirets et tirets bas sont autorisΓ©s, doit commencer par une minuscule.<br />Un fois sauvegardΓ©, l''identifiant ne pourra plus Γͺtre modifiΓ©.'
1096 text_caracters_maximum: "%{count} caractères maximum."
1100 text_caracters_maximum: "%{count} caractères maximum."
1097 text_caracters_minimum: "%{count} caractères minimum."
1101 text_caracters_minimum: "%{count} caractères minimum."
1098 text_length_between: "Longueur comprise entre %{min} et %{max} caractères."
1102 text_length_between: "Longueur comprise entre %{min} et %{max} caractères."
1099 text_tracker_no_workflow: Aucun worflow n'est dΓ©fini pour ce tracker
1103 text_tracker_no_workflow: Aucun worflow n'est dΓ©fini pour ce tracker
1100 text_unallowed_characters: Caractères non autorisés
1104 text_unallowed_characters: Caractères non autorisés
1101 text_comma_separated: Plusieurs valeurs possibles (sΓ©parΓ©es par des virgules).
1105 text_comma_separated: Plusieurs valeurs possibles (sΓ©parΓ©es par des virgules).
1102 text_line_separated: Plusieurs valeurs possibles (une valeur par ligne).
1106 text_line_separated: Plusieurs valeurs possibles (une valeur par ligne).
1103 text_issues_ref_in_commit_messages: RΓ©fΓ©rencement et rΓ©solution des demandes dans les commentaires de commits
1107 text_issues_ref_in_commit_messages: RΓ©fΓ©rencement et rΓ©solution des demandes dans les commentaires de commits
1104 text_issue_added: "La demande %{id} a Γ©tΓ© soumise par %{author}."
1108 text_issue_added: "La demande %{id} a Γ©tΓ© soumise par %{author}."
1105 text_issue_updated: "La demande %{id} a Γ©tΓ© mise Γ  jour par %{author}."
1109 text_issue_updated: "La demande %{id} a Γ©tΓ© mise Γ  jour par %{author}."
1106 text_wiki_destroy_confirmation: Etes-vous sΓ»r de vouloir supprimer ce wiki et tout son contenu ?
1110 text_wiki_destroy_confirmation: Etes-vous sΓ»r de vouloir supprimer ce wiki et tout son contenu ?
1107 text_issue_category_destroy_question: "%{count} demandes sont affectΓ©es Γ  cette catΓ©gorie. Que voulez-vous faire ?"
1111 text_issue_category_destroy_question: "%{count} demandes sont affectΓ©es Γ  cette catΓ©gorie. Que voulez-vous faire ?"
1108 text_issue_category_destroy_assignments: N'affecter les demandes Γ  aucune autre catΓ©gorie
1112 text_issue_category_destroy_assignments: N'affecter les demandes Γ  aucune autre catΓ©gorie
1109 text_issue_category_reassign_to: RΓ©affecter les demandes Γ  cette catΓ©gorie
1113 text_issue_category_reassign_to: RΓ©affecter les demandes Γ  cette catΓ©gorie
1110 text_user_mail_option: "Pour les projets non sΓ©lectionnΓ©s, vous recevrez seulement des notifications pour ce que vous surveillez ou Γ  quoi vous participez (exemple: demandes dont vous Γͺtes l'auteur ou la personne assignΓ©e)."
1114 text_user_mail_option: "Pour les projets non sΓ©lectionnΓ©s, vous recevrez seulement des notifications pour ce que vous surveillez ou Γ  quoi vous participez (exemple: demandes dont vous Γͺtes l'auteur ou la personne assignΓ©e)."
1111 text_no_configuration_data: "Les rΓ΄les, trackers, statuts et le workflow ne sont pas encore paramΓ©trΓ©s.\nIl est vivement recommandΓ© de charger le paramΓ©trage par defaut. Vous pourrez le modifier une fois chargΓ©."
1115 text_no_configuration_data: "Les rΓ΄les, trackers, statuts et le workflow ne sont pas encore paramΓ©trΓ©s.\nIl est vivement recommandΓ© de charger le paramΓ©trage par defaut. Vous pourrez le modifier une fois chargΓ©."
1112 text_load_default_configuration: Charger le paramΓ©trage par dΓ©faut
1116 text_load_default_configuration: Charger le paramΓ©trage par dΓ©faut
1113 text_status_changed_by_changeset: "AppliquΓ© par commit %{value}."
1117 text_status_changed_by_changeset: "AppliquΓ© par commit %{value}."
1114 text_time_logged_by_changeset: "AppliquΓ© par commit %{value}"
1118 text_time_logged_by_changeset: "AppliquΓ© par commit %{value}"
1115 text_issues_destroy_confirmation: 'Êtes-vous sûr de vouloir supprimer la ou les demandes(s) selectionnée(s) ?'
1119 text_issues_destroy_confirmation: 'Êtes-vous sûr de vouloir supprimer la ou les demandes(s) selectionnée(s) ?'
1116 text_issues_destroy_descendants_confirmation: "Cela entrainera Γ©galement la suppression de %{count} sous-tΓ’che(s)."
1120 text_issues_destroy_descendants_confirmation: "Cela entrainera Γ©galement la suppression de %{count} sous-tΓ’che(s)."
1117 text_time_entries_destroy_confirmation: "Etes-vous sΓ»r de vouloir supprimer les temps passΓ©s sΓ©lectionnΓ©s ?"
1121 text_time_entries_destroy_confirmation: "Etes-vous sΓ»r de vouloir supprimer les temps passΓ©s sΓ©lectionnΓ©s ?"
1118 text_select_project_modules: 'SΓ©lectionner les modules Γ  activer pour ce projet :'
1122 text_select_project_modules: 'SΓ©lectionner les modules Γ  activer pour ce projet :'
1119 text_default_administrator_account_changed: Compte administrateur par dΓ©faut changΓ©
1123 text_default_administrator_account_changed: Compte administrateur par dΓ©faut changΓ©
1120 text_file_repository_writable: RΓ©pertoire de stockage des fichiers accessible en Γ©criture
1124 text_file_repository_writable: RΓ©pertoire de stockage des fichiers accessible en Γ©criture
1121 text_plugin_assets_writable: RΓ©pertoire public des plugins accessible en Γ©criture
1125 text_plugin_assets_writable: RΓ©pertoire public des plugins accessible en Γ©criture
1122 text_rmagick_available: Bibliothèque RMagick présente (optionnelle)
1126 text_rmagick_available: Bibliothèque RMagick présente (optionnelle)
1123 text_convert_available: Binaire convert de ImageMagick prΓ©sent (optionel)
1127 text_convert_available: Binaire convert de ImageMagick prΓ©sent (optionel)
1124 text_destroy_time_entries_question: "%{hours} heures ont Γ©tΓ© enregistrΓ©es sur les demandes Γ  supprimer. Que voulez-vous faire ?"
1128 text_destroy_time_entries_question: "%{hours} heures ont Γ©tΓ© enregistrΓ©es sur les demandes Γ  supprimer. Que voulez-vous faire ?"
1125 text_destroy_time_entries: Supprimer les heures
1129 text_destroy_time_entries: Supprimer les heures
1126 text_assign_time_entries_to_project: Reporter les heures sur le projet
1130 text_assign_time_entries_to_project: Reporter les heures sur le projet
1127 text_reassign_time_entries: 'Reporter les heures sur cette demande:'
1131 text_reassign_time_entries: 'Reporter les heures sur cette demande:'
1128 text_user_wrote: "%{value} a Γ©crit :"
1132 text_user_wrote: "%{value} a Γ©crit :"
1129 text_enumeration_destroy_question: "La valeur Β« %{name} Β» est affectΓ©e Γ  %{count} objet(s)."
1133 text_enumeration_destroy_question: "La valeur Β« %{name} Β» est affectΓ©e Γ  %{count} objet(s)."
1130 text_enumeration_category_reassign_to: 'RΓ©affecter les objets Γ  cette valeur:'
1134 text_enumeration_category_reassign_to: 'RΓ©affecter les objets Γ  cette valeur:'
1131 text_email_delivery_not_configured: "L'envoi de mail n'est pas configurΓ©, les notifications sont dΓ©sactivΓ©es.\nConfigurez votre serveur SMTP dans config/configuration.yml et redΓ©marrez l'application pour les activer."
1135 text_email_delivery_not_configured: "L'envoi de mail n'est pas configurΓ©, les notifications sont dΓ©sactivΓ©es.\nConfigurez votre serveur SMTP dans config/configuration.yml et redΓ©marrez l'application pour les activer."
1132 text_repository_usernames_mapping: "Vous pouvez sΓ©lectionner ou modifier l'utilisateur Redmine associΓ© Γ  chaque nom d'utilisateur figurant dans l'historique du dΓ©pΓ΄t.\nLes utilisateurs avec le mΓͺme identifiant ou la mΓͺme adresse mail seront automatiquement associΓ©s."
1136 text_repository_usernames_mapping: "Vous pouvez sΓ©lectionner ou modifier l'utilisateur Redmine associΓ© Γ  chaque nom d'utilisateur figurant dans l'historique du dΓ©pΓ΄t.\nLes utilisateurs avec le mΓͺme identifiant ou la mΓͺme adresse mail seront automatiquement associΓ©s."
1133 text_diff_truncated: '... Ce diffΓ©rentiel a Γ©tΓ© tronquΓ© car il excΓ¨de la taille maximale pouvant Γͺtre affichΓ©e.'
1137 text_diff_truncated: '... Ce diffΓ©rentiel a Γ©tΓ© tronquΓ© car il excΓ¨de la taille maximale pouvant Γͺtre affichΓ©e.'
1134 text_custom_field_possible_values_info: 'Une ligne par valeur'
1138 text_custom_field_possible_values_info: 'Une ligne par valeur'
1135 text_wiki_page_destroy_question: "Cette page possède %{descendants} sous-page(s) et descendante(s). Que voulez-vous faire ?"
1139 text_wiki_page_destroy_question: "Cette page possède %{descendants} sous-page(s) et descendante(s). Que voulez-vous faire ?"
1136 text_wiki_page_nullify_children: "Conserver les sous-pages en tant que pages racines"
1140 text_wiki_page_nullify_children: "Conserver les sous-pages en tant que pages racines"
1137 text_wiki_page_destroy_children: "Supprimer les sous-pages et toutes leurs descedantes"
1141 text_wiki_page_destroy_children: "Supprimer les sous-pages et toutes leurs descedantes"
1138 text_wiki_page_reassign_children: "RΓ©affecter les sous-pages Γ  cette page"
1142 text_wiki_page_reassign_children: "RΓ©affecter les sous-pages Γ  cette page"
1139 text_own_membership_delete_confirmation: "Vous allez supprimer tout ou partie de vos permissions sur ce projet et ne serez peut-Γͺtre plus autorisΓ© Γ  modifier ce projet.\nEtes-vous sΓ»r de vouloir continuer ?"
1143 text_own_membership_delete_confirmation: "Vous allez supprimer tout ou partie de vos permissions sur ce projet et ne serez peut-Γͺtre plus autorisΓ© Γ  modifier ce projet.\nEtes-vous sΓ»r de vouloir continuer ?"
1140 text_zoom_in: Zoom avant
1144 text_zoom_in: Zoom avant
1141 text_zoom_out: Zoom arrière
1145 text_zoom_out: Zoom arrière
1142 text_warn_on_leaving_unsaved: "Cette page contient du texte non sauvegardΓ© qui sera perdu si vous quittez la page."
1146 text_warn_on_leaving_unsaved: "Cette page contient du texte non sauvegardΓ© qui sera perdu si vous quittez la page."
1143 text_scm_path_encoding_note: "DΓ©faut : UTF-8"
1147 text_scm_path_encoding_note: "DΓ©faut : UTF-8"
1144 text_subversion_repository_note: "Exemples (en fonction des protocoles supportΓ©s) : file:///, http://, https://, svn://, svn+[tunnelscheme]://"
1148 text_subversion_repository_note: "Exemples (en fonction des protocoles supportΓ©s) : file:///, http://, https://, svn://, svn+[tunnelscheme]://"
1145 text_git_repository_note: "Chemin vers un dΓ©pΓ΄t vide et local (exemples : /gitrepo, c:\\gitrepo)"
1149 text_git_repository_note: "Chemin vers un dΓ©pΓ΄t vide et local (exemples : /gitrepo, c:\\gitrepo)"
1146 text_mercurial_repository_note: "Chemin vers un dΓ©pΓ΄t local (exemples : /hgrepo, c:\\hgrepo)"
1150 text_mercurial_repository_note: "Chemin vers un dΓ©pΓ΄t local (exemples : /hgrepo, c:\\hgrepo)"
1147 text_scm_command: Commande
1151 text_scm_command: Commande
1148 text_scm_command_version: Version
1152 text_scm_command_version: Version
1149 text_scm_config: Vous pouvez configurer les commandes des SCM dans config/configuration.yml. Redémarrer l'application après modification.
1153 text_scm_config: Vous pouvez configurer les commandes des SCM dans config/configuration.yml. Redémarrer l'application après modification.
1150 text_scm_command_not_available: Ce SCM n'est pas disponible. Vérifier les paramètres dans la section administration.
1154 text_scm_command_not_available: Ce SCM n'est pas disponible. Vérifier les paramètres dans la section administration.
1151 text_issue_conflict_resolution_overwrite: "Appliquer quand mΓͺme ma mise Γ  jour (les notes prΓ©cΓ©dentes seront conservΓ©es mais des changements pourront Γͺtre Γ©crasΓ©s)"
1155 text_issue_conflict_resolution_overwrite: "Appliquer quand mΓͺme ma mise Γ  jour (les notes prΓ©cΓ©dentes seront conservΓ©es mais des changements pourront Γͺtre Γ©crasΓ©s)"
1152 text_issue_conflict_resolution_add_notes: "Ajouter mes notes et ignorer mes autres changements"
1156 text_issue_conflict_resolution_add_notes: "Ajouter mes notes et ignorer mes autres changements"
1153 text_issue_conflict_resolution_cancel: "Annuler ma mise Γ  jour et rΓ©afficher %{link}"
1157 text_issue_conflict_resolution_cancel: "Annuler ma mise Γ  jour et rΓ©afficher %{link}"
1154 text_account_destroy_confirmation: "Êtes-vous sûr de vouloir continuer ?\nVotre compte sera définitivement supprimé, sans aucune possibilité de le réactiver."
1158 text_account_destroy_confirmation: "Êtes-vous sûr de vouloir continuer ?\nVotre compte sera définitivement supprimé, sans aucune possibilité de le réactiver."
1155 text_session_expiration_settings: "Attention : le changement de ces paramètres peut entrainer l'expiration des sessions utilisateurs en cours, y compris la vôtre."
1159 text_session_expiration_settings: "Attention : le changement de ces paramètres peut entrainer l'expiration des sessions utilisateurs en cours, y compris la vôtre."
1156 text_project_closed: Ce projet est fermΓ© et accessible en lecture seule.
1160 text_project_closed: Ce projet est fermΓ© et accessible en lecture seule.
1157 text_turning_multiple_off: "Si vous dΓ©sactivez les valeurs multiples, les valeurs multiples seront supprimΓ©es pour n'en conserver qu'une par objet."
1161 text_turning_multiple_off: "Si vous dΓ©sactivez les valeurs multiples, les valeurs multiples seront supprimΓ©es pour n'en conserver qu'une par objet."
1158
1162
1159 default_role_manager: Manager
1163 default_role_manager: Manager
1160 default_role_developer: DΓ©veloppeur
1164 default_role_developer: DΓ©veloppeur
1161 default_role_reporter: Rapporteur
1165 default_role_reporter: Rapporteur
1162 default_tracker_bug: Anomalie
1166 default_tracker_bug: Anomalie
1163 default_tracker_feature: Evolution
1167 default_tracker_feature: Evolution
1164 default_tracker_support: Assistance
1168 default_tracker_support: Assistance
1165 default_issue_status_new: Nouveau
1169 default_issue_status_new: Nouveau
1166 default_issue_status_in_progress: En cours
1170 default_issue_status_in_progress: En cours
1167 default_issue_status_resolved: RΓ©solu
1171 default_issue_status_resolved: RΓ©solu
1168 default_issue_status_feedback: Commentaire
1172 default_issue_status_feedback: Commentaire
1169 default_issue_status_closed: FermΓ©
1173 default_issue_status_closed: FermΓ©
1170 default_issue_status_rejected: RejetΓ©
1174 default_issue_status_rejected: RejetΓ©
1171 default_doc_category_user: Documentation utilisateur
1175 default_doc_category_user: Documentation utilisateur
1172 default_doc_category_tech: Documentation technique
1176 default_doc_category_tech: Documentation technique
1173 default_priority_low: Bas
1177 default_priority_low: Bas
1174 default_priority_normal: Normal
1178 default_priority_normal: Normal
1175 default_priority_high: Haut
1179 default_priority_high: Haut
1176 default_priority_urgent: Urgent
1180 default_priority_urgent: Urgent
1177 default_priority_immediate: ImmΓ©diat
1181 default_priority_immediate: ImmΓ©diat
1178 default_activity_design: Conception
1182 default_activity_design: Conception
1179 default_activity_development: DΓ©veloppement
1183 default_activity_development: DΓ©veloppement
1180
1184
1181 enumeration_issue_priorities: PrioritΓ©s des demandes
1185 enumeration_issue_priorities: PrioritΓ©s des demandes
1182 enumeration_doc_categories: CatΓ©gories des documents
1186 enumeration_doc_categories: CatΓ©gories des documents
1183 enumeration_activities: ActivitΓ©s (suivi du temps)
1187 enumeration_activities: ActivitΓ©s (suivi du temps)
1184 enumeration_system_activity: Activité système
1188 enumeration_system_activity: Activité système
1185 description_filter: Filtre
1189 description_filter: Filtre
1186 description_search: Champ de recherche
1190 description_search: Champ de recherche
1187 description_choose_project: Projets
1191 description_choose_project: Projets
1188 description_project_scope: Périmètre de recherche
1192 description_project_scope: Périmètre de recherche
1189 description_notes: Notes
1193 description_notes: Notes
1190 description_message_content: Contenu du message
1194 description_message_content: Contenu du message
1191 description_query_sort_criteria_attribute: Critère de tri
1195 description_query_sort_criteria_attribute: Critère de tri
1192 description_query_sort_criteria_direction: Ordre de tri
1196 description_query_sort_criteria_direction: Ordre de tri
1193 description_user_mail_notification: Option de notification
1197 description_user_mail_notification: Option de notification
1194 description_available_columns: Colonnes disponibles
1198 description_available_columns: Colonnes disponibles
1195 description_selected_columns: Colonnes sΓ©lectionnΓ©es
1199 description_selected_columns: Colonnes sΓ©lectionnΓ©es
1196 description_all_columns: Toutes les colonnes
1200 description_all_columns: Toutes les colonnes
1197 description_issue_category_reassign: Choisir une catΓ©gorie
1201 description_issue_category_reassign: Choisir une catΓ©gorie
1198 description_wiki_subpages_reassign: Choisir une nouvelle page parent
1202 description_wiki_subpages_reassign: Choisir une nouvelle page parent
1199 description_date_range_list: Choisir une pΓ©riode prΓ©dΓ©finie
1203 description_date_range_list: Choisir une pΓ©riode prΓ©dΓ©finie
1200 description_date_range_interval: Choisir une pΓ©riode
1204 description_date_range_interval: Choisir une pΓ©riode
1201 description_date_from: Date de dΓ©but
1205 description_date_from: Date de dΓ©but
1202 description_date_to: Date de fin
1206 description_date_to: Date de fin
1203 text_repository_identifier_info: 'Seuls les lettres minuscules (a-z), chiffres, tirets et tirets bas sont autorisΓ©s.<br />Un fois sauvegardΓ©, l''identifiant ne pourra plus Γͺtre modifiΓ©.'
1207 text_repository_identifier_info: 'Seuls les lettres minuscules (a-z), chiffres, tirets et tirets bas sont autorisΓ©s.<br />Un fois sauvegardΓ©, l''identifiant ne pourra plus Γͺtre modifiΓ©.'
1204 label_parent_task_attributes_derived: CalculΓ© Γ  partir des sous-tΓ’ches
1208 label_parent_task_attributes_derived: CalculΓ© Γ  partir des sous-tΓ’ches
1205 label_parent_task_attributes_independent: IndΓ©pendent des sous-tΓ’ches
1209 label_parent_task_attributes_independent: IndΓ©pendent des sous-tΓ’ches
1206 mail_subject_security_notification: Notification de sΓ©curitΓ©
1210 mail_subject_security_notification: Notification de sΓ©curitΓ©
1207 mail_body_security_notification_change: ! '%{field} modifiΓ©(e).'
1211 mail_body_security_notification_change: ! '%{field} modifiΓ©(e).'
1208 mail_body_security_notification_change_to: ! '%{field} changΓ©(e) en %{value}.'
1212 mail_body_security_notification_change_to: ! '%{field} changΓ©(e) en %{value}.'
1209 mail_body_security_notification_add: ! '%{field} %{value} ajoutΓ©(e).'
1213 mail_body_security_notification_add: ! '%{field} %{value} ajoutΓ©(e).'
1210 mail_body_security_notification_remove: ! '%{field} %{value} supprimΓ©(e).'
1214 mail_body_security_notification_remove: ! '%{field} %{value} supprimΓ©(e).'
1211 mail_body_security_notification_notify_enabled: Les notifications ont Γ©tΓ© activΓ©es pour l'adresse %{value}
1215 mail_body_security_notification_notify_enabled: Les notifications ont Γ©tΓ© activΓ©es pour l'adresse %{value}
1212 mail_body_security_notification_notify_disabled: Les notifications ont Γ©tΓ© dΓ©sactivΓ©es pour l'adresse %{value}
1216 mail_body_security_notification_notify_disabled: Les notifications ont Γ©tΓ© dΓ©sactivΓ©es pour l'adresse %{value}
1213 field_remote_ip: Adresse IP
1217 field_remote_ip: Adresse IP
1214 label_no_preview: No preview available
1218 label_no_preview: No preview available
@@ -1,1389 +1,1391
1 html {overflow-y:scroll;}
1 html {overflow-y:scroll;}
2 body { font-family: Verdana, sans-serif; font-size: 12px; color:#333; margin: 0; padding: 0; min-width: 900px; }
2 body { font-family: Verdana, sans-serif; font-size: 12px; color:#333; margin: 0; padding: 0; min-width: 900px; }
3
3
4 h1, h2, h3, h4 {font-family: "Trebuchet MS", Verdana, sans-serif;padding: 2px 10px 1px 0px;margin: 0 0 10px 0;}
4 h1, h2, h3, h4 {font-family: "Trebuchet MS", Verdana, sans-serif;padding: 2px 10px 1px 0px;margin: 0 0 10px 0;}
5 #content h1, h2, h3, h4 {color: #555;}
5 #content h1, h2, h3, h4 {color: #555;}
6 h2, .wiki h1 {font-size: 20px;}
6 h2, .wiki h1 {font-size: 20px;}
7 h3, .wiki h2 {font-size: 16px;}
7 h3, .wiki h2 {font-size: 16px;}
8 h4, .wiki h3 {font-size: 13px;}
8 h4, .wiki h3 {font-size: 13px;}
9 h4 {border-bottom: 1px dotted #bbb;}
9 h4 {border-bottom: 1px dotted #bbb;}
10 pre, code {font-family: Consolas, Menlo, "Liberation Mono", Courier, monospace;}
10 pre, code {font-family: Consolas, Menlo, "Liberation Mono", Courier, monospace;}
11
11
12 /***** Layout *****/
12 /***** Layout *****/
13 #wrapper {background: white;overflow: hidden;}
13 #wrapper {background: white;overflow: hidden;}
14
14
15 #top-menu {background: #3E5B76; color: #fff; height:1.8em; font-size: 0.8em; padding: 2px 2px 0px 6px;}
15 #top-menu {background: #3E5B76; color: #fff; height:1.8em; font-size: 0.8em; padding: 2px 2px 0px 6px;}
16 #top-menu ul {margin: 0; padding: 0;}
16 #top-menu ul {margin: 0; padding: 0;}
17 #top-menu li {
17 #top-menu li {
18 float:left;
18 float:left;
19 list-style-type:none;
19 list-style-type:none;
20 margin: 0px 0px 0px 0px;
20 margin: 0px 0px 0px 0px;
21 padding: 0px 0px 0px 0px;
21 padding: 0px 0px 0px 0px;
22 white-space:nowrap;
22 white-space:nowrap;
23 }
23 }
24 #top-menu a {color: #fff; margin-right: 8px; font-weight: bold;}
24 #top-menu a {color: #fff; margin-right: 8px; font-weight: bold;}
25 #top-menu #loggedas { float: right; margin-right: 0.5em; color: #fff; }
25 #top-menu #loggedas { float: right; margin-right: 0.5em; color: #fff; }
26
26
27 #account {float:right;}
27 #account {float:right;}
28
28
29 #header {min-height:5.3em;margin:0;background-color:#628DB6;color:#f8f8f8; padding: 4px 8px 20px 6px; position:relative;}
29 #header {min-height:5.3em;margin:0;background-color:#628DB6;color:#f8f8f8; padding: 4px 8px 20px 6px; position:relative;}
30 #header a {color:#f8f8f8;}
30 #header a {color:#f8f8f8;}
31 #header h1 { overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
31 #header h1 { overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
32 #header h1 .breadcrumbs { display:block; font-size: .6em; font-weight: normal; }
32 #header h1 .breadcrumbs { display:block; font-size: .6em; font-weight: normal; }
33 #quick-search {float:right;}
33 #quick-search {float:right;}
34
34
35 #main-menu {position: absolute; bottom: 0px; left:6px; margin-right: -500px; width: 100%;}
35 #main-menu {position: absolute; bottom: 0px; left:6px; margin-right: -500px; width: 100%;}
36 #main-menu ul {margin: 0; padding: 0; width: 100%; white-space: nowrap;}
36 #main-menu ul {margin: 0; padding: 0; width: 100%; white-space: nowrap;}
37 #main-menu li {
37 #main-menu li {
38 float:none;
38 float:none;
39 list-style-type:none;
39 list-style-type:none;
40 margin: 0px 2px 0px 0px;
40 margin: 0px 2px 0px 0px;
41 padding: 0px 0px 0px 0px;
41 padding: 0px 0px 0px 0px;
42 white-space:nowrap;
42 white-space:nowrap;
43 display:inline-block;
43 display:inline-block;
44 }
44 }
45 #main-menu li a {
45 #main-menu li a {
46 display: block;
46 display: block;
47 color: #fff;
47 color: #fff;
48 text-decoration: none;
48 text-decoration: none;
49 font-weight: bold;
49 font-weight: bold;
50 margin: 0;
50 margin: 0;
51 padding: 4px 10px 4px 10px;
51 padding: 4px 10px 4px 10px;
52 }
52 }
53 #main-menu li a:hover {background:#759FCF; color:#fff;}
53 #main-menu li a:hover {background:#759FCF; color:#fff;}
54 #main-menu li:hover ul.menu-children, #main-menu li ul.menu-children.visible {display: block;}
54 #main-menu li:hover ul.menu-children, #main-menu li ul.menu-children.visible {display: block;}
55 #main-menu li a.selected, #main-menu li a.selected:hover {background:#fff; color:#555;}
55 #main-menu li a.selected, #main-menu li a.selected:hover {background:#fff; color:#555;}
56 #main-menu li a.new-object { background-color:#759FCF; }
56 #main-menu li a.new-object { background-color:#759FCF; }
57
57
58 #main-menu .menu-children {
58 #main-menu .menu-children {
59 display: none;
59 display: none;
60 position:absolute;
60 position:absolute;
61 width: inherit;
61 width: inherit;
62 z-index:1;
62 z-index:1;
63 background-color:#fff;
63 background-color:#fff;
64 border-right: 1px solid #759FCF;
64 border-right: 1px solid #759FCF;
65 border-bottom: 1px solid #759FCF;
65 border-bottom: 1px solid #759FCF;
66 border-left: 1px solid #759FCF;
66 border-left: 1px solid #759FCF;
67 }
67 }
68 #main-menu .menu-children li {float:left; clear:both; width:100%;}
68 #main-menu .menu-children li {float:left; clear:both; width:100%;}
69 #main-menu .menu-children li a {color: #555; background-color:#fff; font-weight:normal;}
69 #main-menu .menu-children li a {color: #555; background-color:#fff; font-weight:normal;}
70 #main-menu .menu-children li a:hover {color: #fff; background-color: #759FCF;}
70 #main-menu .menu-children li a:hover {color: #fff; background-color: #759FCF;}
71
71
72 #main-menu .tabs-buttons {
72 #main-menu .tabs-buttons {
73 right: 6px;
73 right: 6px;
74 background-color: transparent;
74 background-color: transparent;
75 border-bottom-color: transparent;
75 border-bottom-color: transparent;
76 }
76 }
77
77
78 #admin-menu ul {margin: 0; padding: 0;}
78 #admin-menu ul {margin: 0; padding: 0;}
79 #admin-menu li {margin: 0; padding: 0 0 6px 0; list-style-type:none;}
79 #admin-menu li {margin: 0; padding: 0 0 6px 0; list-style-type:none;}
80
80
81 #admin-menu a { background-position: 0% 40%; background-repeat: no-repeat; padding-left: 20px; padding-top: 2px; padding-bottom: 3px;}
81 #admin-menu a { background-position: 0% 40%; background-repeat: no-repeat; padding-left: 20px; padding-top: 2px; padding-bottom: 3px;}
82 #admin-menu a.projects { background-image: url(../images/projects.png); }
82 #admin-menu a.projects { background-image: url(../images/projects.png); }
83 #admin-menu a.users { background-image: url(../images/user.png); }
83 #admin-menu a.users { background-image: url(../images/user.png); }
84 #admin-menu a.groups { background-image: url(../images/group.png); }
84 #admin-menu a.groups { background-image: url(../images/group.png); }
85 #admin-menu a.roles { background-image: url(../images/database_key.png); }
85 #admin-menu a.roles { background-image: url(../images/database_key.png); }
86 #admin-menu a.trackers { background-image: url(../images/ticket.png); }
86 #admin-menu a.trackers { background-image: url(../images/ticket.png); }
87 #admin-menu a.issue_statuses { background-image: url(../images/ticket_edit.png); }
87 #admin-menu a.issue_statuses { background-image: url(../images/ticket_edit.png); }
88 #admin-menu a.workflows { background-image: url(../images/ticket_go.png); }
88 #admin-menu a.workflows { background-image: url(../images/ticket_go.png); }
89 #admin-menu a.custom_fields { background-image: url(../images/textfield.png); }
89 #admin-menu a.custom_fields { background-image: url(../images/textfield.png); }
90 #admin-menu a.enumerations { background-image: url(../images/text_list_bullets.png); }
90 #admin-menu a.enumerations { background-image: url(../images/text_list_bullets.png); }
91 #admin-menu a.settings { background-image: url(../images/changeset.png); }
91 #admin-menu a.settings { background-image: url(../images/changeset.png); }
92 #admin-menu a.plugins { background-image: url(../images/plugin.png); }
92 #admin-menu a.plugins { background-image: url(../images/plugin.png); }
93 #admin-menu a.info { background-image: url(../images/help.png); }
93 #admin-menu a.info { background-image: url(../images/help.png); }
94 #admin-menu a.server_authentication { background-image: url(../images/server_key.png); }
94 #admin-menu a.server_authentication { background-image: url(../images/server_key.png); }
95
95
96 #main {background-color:#EEEEEE;}
96 #main {background-color:#EEEEEE;}
97
97
98 #sidebar{ float: right; width: 22%; position: relative; z-index: 9; padding: 0; margin: 0;}
98 #sidebar{ float: right; width: 22%; position: relative; z-index: 9; padding: 0; margin: 0;}
99 * html #sidebar{ width: 22%; }
99 * html #sidebar{ width: 22%; }
100 #sidebar h3{ font-size: 14px; margin-top:14px; color: #666; }
100 #sidebar h3{ font-size: 14px; margin-top:14px; color: #666; }
101 #sidebar hr{ width: 100%; margin: 0 auto; height: 1px; background: #ccc; border: 0; }
101 #sidebar hr{ width: 100%; margin: 0 auto; height: 1px; background: #ccc; border: 0; }
102 * html #sidebar hr{ width: 95%; position: relative; left: -6px; color: #ccc; }
102 * html #sidebar hr{ width: 95%; position: relative; left: -6px; color: #ccc; }
103 #sidebar .contextual { margin-right: 1em; }
103 #sidebar .contextual { margin-right: 1em; }
104 #sidebar ul, ul.flat {margin: 0; padding: 0;}
104 #sidebar ul, ul.flat {margin: 0; padding: 0;}
105 #sidebar ul li, ul.flat li {list-style-type:none;margin: 0px 2px 0px 0px; padding: 0px 0px 0px 0px;}
105 #sidebar ul li, ul.flat li {list-style-type:none;margin: 0px 2px 0px 0px; padding: 0px 0px 0px 0px;}
106 #sidebar div.wiki ul {margin:inherit; padding-left:40px;}
106 #sidebar div.wiki ul {margin:inherit; padding-left:40px;}
107 #sidebar div.wiki ul li {list-style-type:inherit;}
107 #sidebar div.wiki ul li {list-style-type:inherit;}
108
108
109 #content { width: 75%; background-color: #fff; margin: 0px; border-right: 1px solid #ddd; padding: 6px 10px 10px 10px; z-index: 10; }
109 #content { width: 75%; background-color: #fff; margin: 0px; border-right: 1px solid #ddd; padding: 6px 10px 10px 10px; z-index: 10; }
110 * html #content{ width: 75%; padding-left: 0; margin-top: 0px; padding: 6px 10px 10px 10px;}
110 * html #content{ width: 75%; padding-left: 0; margin-top: 0px; padding: 6px 10px 10px 10px;}
111 html>body #content { min-height: 600px; }
111 html>body #content { min-height: 600px; }
112 * html body #content { height: 600px; } /* IE */
112 * html body #content { height: 600px; } /* IE */
113
113
114 #main.nosidebar #sidebar{ display: none; }
114 #main.nosidebar #sidebar{ display: none; }
115 #main.nosidebar #content{ width: auto; border-right: 0; }
115 #main.nosidebar #content{ width: auto; border-right: 0; }
116
116
117 #footer {clear: both; border-top: 1px solid #bbb; font-size: 0.9em; color: #aaa; padding: 5px; text-align:center; background:#fff;}
117 #footer {clear: both; border-top: 1px solid #bbb; font-size: 0.9em; color: #aaa; padding: 5px; text-align:center; background:#fff;}
118
118
119 #login-form {margin:5em auto 2em auto; padding:20px; width:340px; border:1px solid #FDBF3B; background-color:#FFEBC1; border-radius:4px; box-sizing: border-box;}
119 #login-form {margin:5em auto 2em auto; padding:20px; width:340px; border:1px solid #FDBF3B; background-color:#FFEBC1; border-radius:4px; box-sizing: border-box;}
120 #login-form label {display:block; margin-bottom:5px;}
120 #login-form label {display:block; margin-bottom:5px;}
121 #login-form input[type=text], #login-form input[type=password] {border:1px solid #ccc; border-radius:3px; margin-bottom:15px; padding:7px; display:block; width:100%; box-sizing: border-box;}
121 #login-form input[type=text], #login-form input[type=password] {border:1px solid #ccc; border-radius:3px; margin-bottom:15px; padding:7px; display:block; width:100%; box-sizing: border-box;}
122 #login-form label {font-weight:bold;}
122 #login-form label {font-weight:bold;}
123 #login-form label[for=autologin] {font-weight:normal;}
123 #login-form label[for=autologin] {font-weight:normal;}
124 #login-form a.lost_password {float:right; font-weight:normal;}
124 #login-form a.lost_password {float:right; font-weight:normal;}
125 #login-form input#openid_url {background:#fff url(../images/openid-bg.gif) no-repeat 4px 50%; padding-left:24px !important;}
125 #login-form input#openid_url {background:#fff url(../images/openid-bg.gif) no-repeat 4px 50%; padding-left:24px !important;}
126 #login-form input#login-submit {margin-top:15px; padding:7px; display:block; width:100%; box-sizing: border-box;}
126 #login-form input#login-submit {margin-top:15px; padding:7px; display:block; width:100%; box-sizing: border-box;}
127
127
128 div.modal { border-radius:5px; background:#fff; z-index:50; padding:4px;}
128 div.modal { border-radius:5px; background:#fff; z-index:50; padding:4px;}
129 div.modal h3.title {display:none;}
129 div.modal h3.title {display:none;}
130 div.modal p.buttons {text-align:right; margin-bottom:0;}
130 div.modal p.buttons {text-align:right; margin-bottom:0;}
131 div.modal .box p {margin: 0.3em 0;}
131 div.modal .box p {margin: 0.3em 0;}
132
132
133 .clear:after{ content: "."; display: block; height: 0; clear: both; visibility: hidden; }
133 .clear:after{ content: "."; display: block; height: 0; clear: both; visibility: hidden; }
134
134
135 .mobile-show {display: none;}
135 .mobile-show {display: none;}
136
136
137 /***** Links *****/
137 /***** Links *****/
138 a, a:link, a:visited{ color: #169; text-decoration: none; }
138 a, a:link, a:visited{ color: #169; text-decoration: none; }
139 a:hover, a:active{ color: #c61a1a; text-decoration: underline;}
139 a:hover, a:active{ color: #c61a1a; text-decoration: underline;}
140 a img{ border: 0; }
140 a img{ border: 0; }
141
141
142 a.issue.closed, a.issue.closed:link, a.issue.closed:visited { color: #999; text-decoration: line-through; }
142 a.issue.closed, a.issue.closed:link, a.issue.closed:visited { color: #999; text-decoration: line-through; }
143 a.project.closed, a.project.closed:link, a.project.closed:visited { color: #999; }
143 a.project.closed, a.project.closed:link, a.project.closed:visited { color: #999; }
144 a.user.locked, a.user.locked:link, a.user.locked:visited {color: #999;}
144 a.user.locked, a.user.locked:link, a.user.locked:visited {color: #999;}
145
145
146 #sidebar a.selected {line-height:1.7em; padding:1px 3px 2px 2px; margin-left:-2px; background-color:#9DB9D5; color:#fff; border-radius:2px;}
146 #sidebar a.selected {line-height:1.7em; padding:1px 3px 2px 2px; margin-left:-2px; background-color:#9DB9D5; color:#fff; border-radius:2px;}
147 #sidebar a.selected:hover {text-decoration:none;}
147 #sidebar a.selected:hover {text-decoration:none;}
148 #admin-menu a {line-height:1.7em;}
148 #admin-menu a {line-height:1.7em;}
149 #admin-menu a.selected {padding-left: 20px !important; background-position: 2px 40%;}
149 #admin-menu a.selected {padding-left: 20px !important; background-position: 2px 40%;}
150
150
151 a.collapsible {padding-left: 12px; background: url(../images/arrow_expanded.png) no-repeat -3px 40%;}
151 a.collapsible {padding-left: 12px; background: url(../images/arrow_expanded.png) no-repeat -3px 40%;}
152 a.collapsible.collapsed {background: url(../images/arrow_collapsed.png) no-repeat -5px 40%;}
152 a.collapsible.collapsed {background: url(../images/arrow_collapsed.png) no-repeat -5px 40%;}
153
153
154 a#toggle-completed-versions {color:#999;}
154 a#toggle-completed-versions {color:#999;}
155
155
156 a.toggle-checkboxes { margin-left: 5px; padding-left: 12px; background: url(../images/toggle_check.png) no-repeat 0% 50%; }
156 a.toggle-checkboxes { margin-left: 5px; padding-left: 12px; background: url(../images/toggle_check.png) no-repeat 0% 50%; }
157
157
158 /***** Tables *****/
158 /***** Tables *****/
159 table.list, .table-list { border: 1px solid #e4e4e4; border-collapse: collapse; width: 100%; margin-bottom: 4px; }
159 table.list, .table-list { border: 1px solid #e4e4e4; border-collapse: collapse; width: 100%; margin-bottom: 4px; }
160 table.list th, .table-list-header { background-color:#EEEEEE; padding: 4px; white-space:nowrap; font-weight:bold; }
160 table.list th, .table-list-header { background-color:#EEEEEE; padding: 4px; white-space:nowrap; font-weight:bold; }
161 table.list td {text-align:center; vertical-align:top; padding-right:10px;}
161 table.list td {text-align:center; vertical-align:top; padding-right:10px;}
162 table.list td.id { width: 2%; text-align: center;}
162 table.list td.id { width: 2%; text-align: center;}
163 table.list td.name, table.list td.description, table.list td.subject, table.list td.comments, table.list td.roles {text-align: left;}
163 table.list td.name, table.list td.description, table.list td.subject, table.list td.comments, table.list td.roles {text-align: left;}
164 table.list td.tick {width:15%}
164 table.list td.tick {width:15%}
165 table.list td.checkbox { width: 15px; padding: 2px 0 0 0; }
165 table.list td.checkbox { width: 15px; padding: 2px 0 0 0; }
166 table.list td.checkbox input {padding:0px;}
166 table.list td.checkbox input {padding:0px;}
167 table.list td.buttons, div.buttons { white-space:nowrap; text-align: right; }
167 table.list td.buttons, div.buttons { white-space:nowrap; text-align: right; }
168 table.list td.buttons a, div.buttons a { margin-right: 0.6em; }
168 table.list td.buttons a, div.buttons a { margin-right: 0.6em; }
169 table.list td.buttons img, div.buttons img {vertical-align:middle;}
169 table.list td.buttons img, div.buttons img {vertical-align:middle;}
170 table.list td.reorder {width:15%; white-space:nowrap; text-align:center; }
170 table.list td.reorder {width:15%; white-space:nowrap; text-align:center; }
171 table.list table.progress td {padding-right:0px;}
171 table.list table.progress td {padding-right:0px;}
172 table.list caption { text-align: left; padding: 0.5em 0.5em 0.5em 0; }
172 table.list caption { text-align: left; padding: 0.5em 0.5em 0.5em 0; }
173 #role-permissions-trackers table.list th {white-space:normal;}
173 #role-permissions-trackers table.list th {white-space:normal;}
174
174
175 .table-list-cell {display: table-cell; vertical-align: top; padding:2px; }
175 .table-list-cell {display: table-cell; vertical-align: top; padding:2px; }
176
176
177 tr.project td.name a { white-space:nowrap; }
177 tr.project td.name a { white-space:nowrap; }
178 tr.project.closed, tr.project.archived { color: #aaa; }
178 tr.project.closed, tr.project.archived { color: #aaa; }
179 tr.project.closed a, tr.project.archived a { color: #aaa; }
179 tr.project.closed a, tr.project.archived a { color: #aaa; }
180
180
181 tr.project.idnt td.name span {background: url(../images/bullet_arrow_right.png) no-repeat 0 50%; padding-left: 16px;}
181 tr.project.idnt td.name span {background: url(../images/bullet_arrow_right.png) no-repeat 0 50%; padding-left: 16px;}
182 tr.project.idnt-1 td.name {padding-left: 0.5em;}
182 tr.project.idnt-1 td.name {padding-left: 0.5em;}
183 tr.project.idnt-2 td.name {padding-left: 2em;}
183 tr.project.idnt-2 td.name {padding-left: 2em;}
184 tr.project.idnt-3 td.name {padding-left: 3.5em;}
184 tr.project.idnt-3 td.name {padding-left: 3.5em;}
185 tr.project.idnt-4 td.name {padding-left: 5em;}
185 tr.project.idnt-4 td.name {padding-left: 5em;}
186 tr.project.idnt-5 td.name {padding-left: 6.5em;}
186 tr.project.idnt-5 td.name {padding-left: 6.5em;}
187 tr.project.idnt-6 td.name {padding-left: 8em;}
187 tr.project.idnt-6 td.name {padding-left: 8em;}
188 tr.project.idnt-7 td.name {padding-left: 9.5em;}
188 tr.project.idnt-7 td.name {padding-left: 9.5em;}
189 tr.project.idnt-8 td.name {padding-left: 11em;}
189 tr.project.idnt-8 td.name {padding-left: 11em;}
190 tr.project.idnt-9 td.name {padding-left: 12.5em;}
190 tr.project.idnt-9 td.name {padding-left: 12.5em;}
191
191
192 tr.issue { text-align: center; white-space: nowrap; }
192 tr.issue { text-align: center; white-space: nowrap; }
193 tr.issue td.subject, tr.issue td.category, td.assigned_to, tr.issue td.string, tr.issue td.text, tr.issue td.list, tr.issue td.relations, tr.issue td.parent { white-space: normal; }
193 tr.issue td.subject, tr.issue td.category, td.assigned_to, tr.issue td.string, tr.issue td.text, tr.issue td.list, tr.issue td.relations, tr.issue td.parent { white-space: normal; }
194 tr.issue td.relations { text-align: left; }
194 tr.issue td.relations { text-align: left; }
195 tr.issue td.done_ratio table.progress { margin-left:auto; margin-right: auto;}
195 tr.issue td.done_ratio table.progress { margin-left:auto; margin-right: auto;}
196 tr.issue td.relations span {white-space: nowrap;}
196 tr.issue td.relations span {white-space: nowrap;}
197 table.issues td.description {color:#777; font-size:90%; padding:4px 4px 4px 24px; text-align:left; white-space:normal;}
197 table.issues td.description {color:#777; font-size:90%; padding:4px 4px 4px 24px; text-align:left; white-space:normal;}
198 table.issues td.description pre {white-space:normal;}
198 table.issues td.description pre {white-space:normal;}
199
199
200 tr.issue.idnt td.subject {background: url(../images/bullet_arrow_right.png) no-repeat 0 50%;}
200 tr.issue.idnt td.subject {background: url(../images/bullet_arrow_right.png) no-repeat 0 50%;}
201 tr.issue.idnt-1 td.subject {padding-left: 24px; background-position: 8px 50%;}
201 tr.issue.idnt-1 td.subject {padding-left: 24px; background-position: 8px 50%;}
202 tr.issue.idnt-2 td.subject {padding-left: 40px; background-position: 24px 50%;}
202 tr.issue.idnt-2 td.subject {padding-left: 40px; background-position: 24px 50%;}
203 tr.issue.idnt-3 td.subject {padding-left: 56px; background-position: 40px 50%;}
203 tr.issue.idnt-3 td.subject {padding-left: 56px; background-position: 40px 50%;}
204 tr.issue.idnt-4 td.subject {padding-left: 72px; background-position: 56px 50%;}
204 tr.issue.idnt-4 td.subject {padding-left: 72px; background-position: 56px 50%;}
205 tr.issue.idnt-5 td.subject {padding-left: 88px; background-position: 72px 50%;}
205 tr.issue.idnt-5 td.subject {padding-left: 88px; background-position: 72px 50%;}
206 tr.issue.idnt-6 td.subject {padding-left: 104px; background-position: 88px 50%;}
206 tr.issue.idnt-6 td.subject {padding-left: 104px; background-position: 88px 50%;}
207 tr.issue.idnt-7 td.subject {padding-left: 120px; background-position: 104px 50%;}
207 tr.issue.idnt-7 td.subject {padding-left: 120px; background-position: 104px 50%;}
208 tr.issue.idnt-8 td.subject {padding-left: 136px; background-position: 120px 50%;}
208 tr.issue.idnt-8 td.subject {padding-left: 136px; background-position: 120px 50%;}
209 tr.issue.idnt-9 td.subject {padding-left: 152px; background-position: 136px 50%;}
209 tr.issue.idnt-9 td.subject {padding-left: 152px; background-position: 136px 50%;}
210
210
211 table.issue-report {table-layout:fixed;}
211 table.issue-report {table-layout:fixed;}
212
212
213 tr.entry { border: 1px solid #f8f8f8; }
213 tr.entry { border: 1px solid #f8f8f8; }
214 tr.entry td { white-space: nowrap; }
214 tr.entry td { white-space: nowrap; }
215 tr.entry td.filename {width:30%; text-align:left;}
215 tr.entry td.filename {width:30%; text-align:left;}
216 tr.entry td.filename_no_report {width:70%; text-align:left;}
216 tr.entry td.filename_no_report {width:70%; text-align:left;}
217 tr.entry td.size { text-align: right; font-size: 90%; }
217 tr.entry td.size { text-align: right; font-size: 90%; }
218 tr.entry td.revision, tr.entry td.author { text-align: center; }
218 tr.entry td.revision, tr.entry td.author { text-align: center; }
219 tr.entry td.age { text-align: right; }
219 tr.entry td.age { text-align: right; }
220 tr.entry.file td.filename a { margin-left: 16px; }
220 tr.entry.file td.filename a { margin-left: 16px; }
221 tr.entry.file td.filename_no_report a { margin-left: 16px; }
221 tr.entry.file td.filename_no_report a { margin-left: 16px; }
222
222
223 tr span.expander {background-image: url(../images/bullet_toggle_plus.png); padding-left: 8px; margin-left: 0; cursor: pointer;}
223 tr span.expander {background-image: url(../images/bullet_toggle_plus.png); padding-left: 8px; margin-left: 0; cursor: pointer;}
224 tr.open span.expander {background-image: url(../images/bullet_toggle_minus.png);}
224 tr.open span.expander {background-image: url(../images/bullet_toggle_minus.png);}
225
225
226 tr.changeset { height: 20px }
226 tr.changeset { height: 20px }
227 tr.changeset ul, ol { margin-top: 0px; margin-bottom: 0px; }
227 tr.changeset ul, ol { margin-top: 0px; margin-bottom: 0px; }
228 tr.changeset td.revision_graph { width: 15%; background-color: #fffffb; }
228 tr.changeset td.revision_graph { width: 15%; background-color: #fffffb; }
229 tr.changeset td.author { text-align: center; width: 15%; white-space:nowrap;}
229 tr.changeset td.author { text-align: center; width: 15%; white-space:nowrap;}
230 tr.changeset td.committed_on { text-align: center; width: 15%; white-space:nowrap;}
230 tr.changeset td.committed_on { text-align: center; width: 15%; white-space:nowrap;}
231
231
232 table.files tbody th {text-align:left;}
232 table.files tbody th {text-align:left;}
233 table.files tr.file td.filename { text-align: left; padding-left: 24px; }
233 table.files tr.file td.filename { text-align: left; padding-left: 24px; }
234 table.files tr.file td.digest { font-size: 80%; }
234 table.files tr.file td.digest { font-size: 80%; }
235
235
236 table.members td.roles, table.memberships td.roles { width: 45%; }
236 table.members td.roles, table.memberships td.roles { width: 45%; }
237
237
238 tr.message { height: 2.6em; }
238 tr.message { height: 2.6em; }
239 tr.message td.subject { padding-left: 20px; }
239 tr.message td.subject { padding-left: 20px; }
240 tr.message td.created_on { white-space: nowrap; }
240 tr.message td.created_on { white-space: nowrap; }
241 tr.message td.last_message { font-size: 80%; white-space: nowrap; }
241 tr.message td.last_message { font-size: 80%; white-space: nowrap; }
242 tr.message.locked td.subject { background: url(../images/locked.png) no-repeat 0 1px; }
242 tr.message.locked td.subject { background: url(../images/locked.png) no-repeat 0 1px; }
243 tr.message.sticky td.subject { background: url(../images/bullet_go.png) no-repeat 0 1px; font-weight: bold; }
243 tr.message.sticky td.subject { background: url(../images/bullet_go.png) no-repeat 0 1px; font-weight: bold; }
244
244
245 tr.version.closed, tr.version.closed a { color: #999; }
245 tr.version.closed, tr.version.closed a { color: #999; }
246 tr.version td.name { padding-left: 20px; }
246 tr.version td.name { padding-left: 20px; }
247 tr.version.shared td.name { background: url(../images/link.png) no-repeat 0% 70%; }
247 tr.version.shared td.name { background: url(../images/link.png) no-repeat 0% 70%; }
248 tr.version td.date, tr.version td.status, tr.version td.sharing { text-align: center; white-space:nowrap; }
248 tr.version td.date, tr.version td.status, tr.version td.sharing { text-align: center; white-space:nowrap; }
249
249
250 tr.user td {width:13%;white-space: nowrap;}
250 tr.user td {width:13%;white-space: nowrap;}
251 td.username, td.firstname, td.lastname, td.email {text-align:left !important;}
251 td.username, td.firstname, td.lastname, td.email {text-align:left !important;}
252 tr.user td.email { width:18%; }
252 tr.user td.email { width:18%; }
253 tr.user.locked, tr.user.registered { color: #aaa; }
253 tr.user.locked, tr.user.registered { color: #aaa; }
254 tr.user.locked a, tr.user.registered a { color: #aaa; }
254 tr.user.locked a, tr.user.registered a { color: #aaa; }
255
255
256 table.permissions td.role {color:#999;font-size:90%;font-weight:normal !important;text-align:center;vertical-align:bottom;}
256 table.permissions td.role {color:#999;font-size:90%;font-weight:normal !important;text-align:center;vertical-align:bottom;}
257
257
258 tr.wiki-page-version td.updated_on, tr.wiki-page-version td.author {text-align:center;}
258 tr.wiki-page-version td.updated_on, tr.wiki-page-version td.author {text-align:center;}
259
259
260 tr.time-entry { text-align: center; white-space: nowrap; }
260 tr.time-entry { text-align: center; white-space: nowrap; }
261 tr.time-entry td.issue, tr.time-entry td.comments, tr.time-entry td.subject, tr.time-entry td.activity { text-align: left; white-space: normal; }
261 tr.time-entry td.issue, tr.time-entry td.comments, tr.time-entry td.subject, tr.time-entry td.activity { text-align: left; white-space: normal; }
262 td.hours { text-align: right; font-weight: bold; padding-right: 0.5em; }
262 td.hours { text-align: right; font-weight: bold; padding-right: 0.5em; }
263 td.hours .hours-dec { font-size: 0.9em; }
263 td.hours .hours-dec { font-size: 0.9em; }
264
264
265 table.plugins td { vertical-align: middle; }
265 table.plugins td { vertical-align: middle; }
266 table.plugins td.configure { text-align: right; padding-right: 1em; }
266 table.plugins td.configure { text-align: right; padding-right: 1em; }
267 table.plugins span.name { font-weight: bold; display: block; margin-bottom: 6px; }
267 table.plugins span.name { font-weight: bold; display: block; margin-bottom: 6px; }
268 table.plugins span.description { display: block; font-size: 0.9em; }
268 table.plugins span.description { display: block; font-size: 0.9em; }
269 table.plugins span.url { display: block; font-size: 0.9em; }
269 table.plugins span.url { display: block; font-size: 0.9em; }
270
270
271 tr.group td { padding: 0.8em 0 0.5em 0.3em; border-bottom: 1px solid #ccc; text-align:left; }
271 tr.group td { padding: 0.8em 0 0.5em 0.3em; border-bottom: 1px solid #ccc; text-align:left; }
272 tr.group span.name {font-weight:bold;}
272 tr.group span.name {font-weight:bold;}
273 tr.group span.count {font-weight:bold; position:relative; top:-1px; color:#fff; font-size:10px; background:#9DB9D5; padding:0px 6px 1px 6px; border-radius:3px; margin-left:4px;}
273 tr.group span.count {font-weight:bold; position:relative; top:-1px; color:#fff; font-size:10px; background:#9DB9D5; padding:0px 6px 1px 6px; border-radius:3px; margin-left:4px;}
274 tr.group span.totals {color: #aaa; font-size: 80%;}
274 tr.group span.totals {color: #aaa; font-size: 80%;}
275 tr.group span.totals .value {font-weight:bold; color:#777;}
275 tr.group span.totals .value {font-weight:bold; color:#777;}
276 tr.group a.toggle-all { color: #aaa; font-size: 80%; display:none; float:right; margin-right:4px;}
276 tr.group a.toggle-all { color: #aaa; font-size: 80%; display:none; float:right; margin-right:4px;}
277 tr.group:hover a.toggle-all { display:inline;}
277 tr.group:hover a.toggle-all { display:inline;}
278 a.toggle-all:hover {text-decoration:none;}
278 a.toggle-all:hover {text-decoration:none;}
279
279
280 table.list tbody tr:hover { background-color:#ffffdd; }
280 table.list tbody tr:hover { background-color:#ffffdd; }
281 table.list tbody tr.group:hover { background-color:inherit; }
281 table.list tbody tr.group:hover { background-color:inherit; }
282 table td {padding:2px;}
282 table td {padding:2px;}
283 table p {margin:0;}
283 table p {margin:0;}
284 .odd {background-color:#f6f7f8;}
284 .odd {background-color:#f6f7f8;}
285 .even {background-color: #fff;}
285 .even {background-color: #fff;}
286
286
287 tr.builtin td.name {font-style:italic;}
287 tr.builtin td.name {font-style:italic;}
288
288
289 a.sort { padding-right: 16px; background-position: 100% 50%; background-repeat: no-repeat; }
289 a.sort { padding-right: 16px; background-position: 100% 50%; background-repeat: no-repeat; }
290 a.sort.asc { background-image: url(../images/sort_asc.png); }
290 a.sort.asc { background-image: url(../images/sort_asc.png); }
291 a.sort.desc { background-image: url(../images/sort_desc.png); }
291 a.sort.desc { background-image: url(../images/sort_desc.png); }
292
292
293 table.boards a.board, h3.comments { background: url(../images/comment.png) no-repeat 0% 50%; padding-left: 20px; }
293 table.boards a.board, h3.comments { background: url(../images/comment.png) no-repeat 0% 50%; padding-left: 20px; }
294 table.boards td.last-message {text-align:left;font-size:80%;}
294 table.boards td.last-message {text-align:left;font-size:80%;}
295
295
296 div.table-list.boards .table-list-cell.name {width: 30%;}
296 div.table-list.boards .table-list-cell.name {width: 30%;}
297
297
298 table.messages td.last_message {text-align:left;}
298 table.messages td.last_message {text-align:left;}
299
299
300 #query_form_content {font-size:90%;}
300 #query_form_content {font-size:90%;}
301
301
302 .query_sort_criteria_count {
302 .query_sort_criteria_count {
303 display: inline-block;
303 display: inline-block;
304 min-width: 1em;
304 min-width: 1em;
305 }
305 }
306
306
307 table.query-columns {
307 table.query-columns {
308 border-collapse: collapse;
308 border-collapse: collapse;
309 border: 0;
309 border: 0;
310 }
310 }
311
311
312 table.query-columns td.buttons {
312 table.query-columns td.buttons {
313 vertical-align: middle;
313 vertical-align: middle;
314 text-align: center;
314 text-align: center;
315 }
315 }
316 table.query-columns td.buttons input[type=button] {width:35px;}
316 table.query-columns td.buttons input[type=button] {width:35px;}
317 .query-totals {text-align:right;}
317 .query-totals {text-align:right;}
318 .query-totals>span {margin-left:0.6em;}
318 .query-totals>span {margin-left:0.6em;}
319 .query-totals .value {font-weight:bold;}
319 .query-totals .value {font-weight:bold;}
320 body.controller-issues .query-totals {margin-top:-2.3em;}
320 body.controller-issues .query-totals {margin-top:-2.3em;}
321
321
322 td.center {text-align:center;}
322 td.center {text-align:center;}
323
323
324 h3.version { background: url(../images/package.png) no-repeat 0% 50%; padding-left: 20px; }
324 h3.version { background: url(../images/package.png) no-repeat 0% 50%; padding-left: 20px; }
325
325
326 div.issues h3 { background: url(../images/ticket.png) no-repeat 0% 50%; padding-left: 20px; }
326 div.issues h3 { background: url(../images/ticket.png) no-repeat 0% 50%; padding-left: 20px; }
327 div.members h3 { background: url(../images/group.png) no-repeat 0% 50%; padding-left: 20px; }
327 div.members h3 { background: url(../images/group.png) no-repeat 0% 50%; padding-left: 20px; }
328 div.news h3 { background: url(../images/news.png) no-repeat 0% 50%; padding-left: 20px; }
328 div.news h3 { background: url(../images/news.png) no-repeat 0% 50%; padding-left: 20px; }
329 div.projects h3 { background: url(../images/projects.png) no-repeat 0% 50%; padding-left: 20px; }
329 div.projects h3 { background: url(../images/projects.png) no-repeat 0% 50%; padding-left: 20px; }
330 div.spent_time h3 { background: url(../images/time.png) no-repeat 0% 50%; padding-left: 20px; }
330 div.spent_time h3 { background: url(../images/time.png) no-repeat 0% 50%; padding-left: 20px; }
331
331
332 #watchers select {width: 95%; display: block;}
332 #watchers select {width: 95%; display: block;}
333 #watchers a.delete {opacity: 0.4; margin-left: 5px;}
333 #watchers a.delete {opacity: 0.4; margin-left: 5px;}
334 #watchers a.delete:hover {opacity: 1;}
334 #watchers a.delete:hover {opacity: 1;}
335 #watchers img.gravatar {margin: 0 4px 2px 0;}
335 #watchers img.gravatar {margin: 0 4px 2px 0;}
336
336
337 span#watchers_inputs {overflow:auto; display:block;}
337 span#watchers_inputs {overflow:auto; display:block;}
338 span.search_for_watchers {display:block;}
338 span.search_for_watchers {display:block;}
339 span.search_for_watchers, span.add_attachment {font-size:80%; line-height:2.5em;}
339 span.search_for_watchers, span.add_attachment {font-size:80%; line-height:2.5em;}
340 span.search_for_watchers a, span.add_attachment a {padding-left:16px; background: url(../images/bullet_add.png) no-repeat 0 50%; }
340 span.search_for_watchers a, span.add_attachment a {padding-left:16px; background: url(../images/bullet_add.png) no-repeat 0 50%; }
341
341
342
342
343 .highlight { background-color: #FCFD8D;}
343 .highlight { background-color: #FCFD8D;}
344 .highlight.token-1 { background-color: #faa;}
344 .highlight.token-1 { background-color: #faa;}
345 .highlight.token-2 { background-color: #afa;}
345 .highlight.token-2 { background-color: #afa;}
346 .highlight.token-3 { background-color: #aaf;}
346 .highlight.token-3 { background-color: #aaf;}
347
347
348 .box{
348 .box{
349 padding:6px;
349 padding:6px;
350 margin-bottom: 10px;
350 margin-bottom: 10px;
351 background-color:#f6f6f6;
351 background-color:#f6f6f6;
352 color:#505050;
352 color:#505050;
353 line-height:1.5em;
353 line-height:1.5em;
354 border: 1px solid #e4e4e4;
354 border: 1px solid #e4e4e4;
355 word-wrap: break-word;
355 word-wrap: break-word;
356 border-radius: 3px;
356 border-radius: 3px;
357 }
357 }
358
358
359 div.square {
359 div.square {
360 border: 1px solid #999;
360 border: 1px solid #999;
361 float: left;
361 float: left;
362 margin: .3em .4em 0 .4em;
362 margin: .3em .4em 0 .4em;
363 overflow: hidden;
363 overflow: hidden;
364 width: .6em; height: .6em;
364 width: .6em; height: .6em;
365 }
365 }
366 .contextual {float:right; white-space: nowrap; line-height:1.4em;margin:5px 0px; padding-left: 10px; font-size:0.9em;}
366 .contextual {float:right; white-space: nowrap; line-height:1.4em;margin:5px 0px; padding-left: 10px; font-size:0.9em;}
367 .contextual input, .contextual select {font-size:0.9em;}
367 .contextual input, .contextual select {font-size:0.9em;}
368 .message .contextual { margin-top: 0; }
368 .message .contextual { margin-top: 0; }
369
369
370 .splitcontent {overflow:auto;}
370 .splitcontent {overflow:auto;}
371 .splitcontentleft{float:left; width:49%;}
371 .splitcontentleft{float:left; width:49%;}
372 .splitcontentright{float:right; width:49%;}
372 .splitcontentright{float:right; width:49%;}
373 form {display: inline;}
373 form {display: inline;}
374 input, select {vertical-align: middle; margin-top: 1px; margin-bottom: 1px;}
374 input, select {vertical-align: middle; margin-top: 1px; margin-bottom: 1px;}
375 fieldset {border: 1px solid #e4e4e4; margin:0;}
375 fieldset {border: 1px solid #e4e4e4; margin:0;}
376 legend {color: #333;}
376 legend {color: #333;}
377 hr { width: 100%; height: 1px; background: #ccc; border: 0;}
377 hr { width: 100%; height: 1px; background: #ccc; border: 0;}
378 blockquote { font-style: italic; border-left: 3px solid #e0e0e0; padding-left: 0.6em; margin-left: 2.4em;}
378 blockquote { font-style: italic; border-left: 3px solid #e0e0e0; padding-left: 0.6em; margin-left: 2.4em;}
379 blockquote blockquote { margin-left: 0;}
379 blockquote blockquote { margin-left: 0;}
380 abbr, span.field-description[title] { border-bottom: 1px dotted #aaa; cursor: help; }
380 abbr, span.field-description[title] { border-bottom: 1px dotted #aaa; cursor: help; }
381 textarea.wiki-edit {width:99%; resize:vertical;}
381 textarea.wiki-edit {width:99%; resize:vertical;}
382 body.textarea-monospace textarea.wiki-edit {font-family: Consolas, Menlo, "Liberation Mono", Courier, monospace; font-size: 12px;}
383 body.textarea-proportional textarea.wiki-edit {font-family: Verdana, sans-serif; font-size: 12px;}
382 li p {margin-top: 0;}
384 li p {margin-top: 0;}
383 div.issue {background:#ffffdd; padding:6px; margin-bottom:6px; border: 1px solid #d7d7d7; border-radius:3px;}
385 div.issue {background:#ffffdd; padding:6px; margin-bottom:6px; border: 1px solid #d7d7d7; border-radius:3px;}
384 p.breadcrumb { font-size: 0.9em; margin: 4px 0 4px 0;}
386 p.breadcrumb { font-size: 0.9em; margin: 4px 0 4px 0;}
385 p.subtitle { font-size: 0.9em; margin: -6px 0 12px 0; font-style: italic; }
387 p.subtitle { font-size: 0.9em; margin: -6px 0 12px 0; font-style: italic; }
386 p.footnote { font-size: 0.9em; margin-top: 0px; margin-bottom: 0px; }
388 p.footnote { font-size: 0.9em; margin-top: 0px; margin-bottom: 0px; }
387 .ltr {direction:ltr !important; unicode-bidi:bidi-override;}
389 .ltr {direction:ltr !important; unicode-bidi:bidi-override;}
388 .rtl {direction:rtl !important; unicode-bidi:bidi-override;}
390 .rtl {direction:rtl !important; unicode-bidi:bidi-override;}
389
391
390 div.issue div.subject div div { padding-left: 16px; }
392 div.issue div.subject div div { padding-left: 16px; }
391 div.issue div.subject p {margin: 0; margin-bottom: 0.1em; font-size: 90%; color: #999;}
393 div.issue div.subject p {margin: 0; margin-bottom: 0.1em; font-size: 90%; color: #999;}
392 div.issue div.subject>div>p { margin-top: 0.5em; }
394 div.issue div.subject>div>p { margin-top: 0.5em; }
393 div.issue div.subject h3 {margin: 0; margin-bottom: 0.1em;}
395 div.issue div.subject h3 {margin: 0; margin-bottom: 0.1em;}
394 div.issue span.private, div.journal span.private { position:relative; bottom: 2px; text-transform: uppercase; background: #d22; color: #fff; font-weight:bold; padding: 0px 2px 0px 2px; font-size: 60%; margin-right: 2px; border-radius: 2px;}
396 div.issue span.private, div.journal span.private { position:relative; bottom: 2px; text-transform: uppercase; background: #d22; color: #fff; font-weight:bold; padding: 0px 2px 0px 2px; font-size: 60%; margin-right: 2px; border-radius: 2px;}
395 div.issue .next-prev-links {color:#999;}
397 div.issue .next-prev-links {color:#999;}
396 div.issue .attributes {margin-top: 2em;}
398 div.issue .attributes {margin-top: 2em;}
397 div.issue .attribute {padding-left:180px; clear:left; min-height: 1.8em;}
399 div.issue .attribute {padding-left:180px; clear:left; min-height: 1.8em;}
398 div.issue .attribute .label {width: 170px; margin-left:-180px; font-weight:bold; float:left;}
400 div.issue .attribute .label {width: 170px; margin-left:-180px; font-weight:bold; float:left;}
399 div.issue.overdue .due-date .value { color: #c22; }
401 div.issue.overdue .due-date .value { color: #c22; }
400
402
401 #issue_tree table.issues, #relations table.issues { border: 0; }
403 #issue_tree table.issues, #relations table.issues { border: 0; }
402 #issue_tree td.checkbox, #relations td.checkbox {display:none;}
404 #issue_tree td.checkbox, #relations td.checkbox {display:none;}
403 #relations td.buttons {padding:0;}
405 #relations td.buttons {padding:0;}
404
406
405 fieldset.collapsible {border-width: 1px 0 0 0;}
407 fieldset.collapsible {border-width: 1px 0 0 0;}
406 fieldset.collapsible>legend { padding-left: 16px; background: url(../images/arrow_expanded.png) no-repeat 0% 40%; cursor:pointer; }
408 fieldset.collapsible>legend { padding-left: 16px; background: url(../images/arrow_expanded.png) no-repeat 0% 40%; cursor:pointer; }
407 fieldset.collapsible.collapsed>legend { background-image: url(../images/arrow_collapsed.png); }
409 fieldset.collapsible.collapsed>legend { background-image: url(../images/arrow_collapsed.png); }
408
410
409 fieldset#date-range p { margin: 2px 0 2px 0; }
411 fieldset#date-range p { margin: 2px 0 2px 0; }
410 fieldset#filters table { border-collapse: collapse; }
412 fieldset#filters table { border-collapse: collapse; }
411 fieldset#filters table td { padding: 0; vertical-align: middle; }
413 fieldset#filters table td { padding: 0; vertical-align: middle; }
412 fieldset#filters tr.filter { height: 2.1em; }
414 fieldset#filters tr.filter { height: 2.1em; }
413 fieldset#filters td.field { width:230px; }
415 fieldset#filters td.field { width:230px; }
414 fieldset#filters td.operator { width:130px; }
416 fieldset#filters td.operator { width:130px; }
415 fieldset#filters td.operator select {max-width:120px;}
417 fieldset#filters td.operator select {max-width:120px;}
416 fieldset#filters td.values { white-space:nowrap; }
418 fieldset#filters td.values { white-space:nowrap; }
417 fieldset#filters td.values select {min-width:130px; max-width:200px;}
419 fieldset#filters td.values select {min-width:130px; max-width:200px;}
418 fieldset#filters td.values input {height:1em;}
420 fieldset#filters td.values input {height:1em;}
419
421
420 #filters-table {width:60%; float:left;}
422 #filters-table {width:60%; float:left;}
421 .add-filter {width:35%; float:right; text-align: right; vertical-align: top;}
423 .add-filter {width:35%; float:right; text-align: right; vertical-align: top;}
422
424
423 #issue_is_private_wrap {float:right; margin-right:1em;}
425 #issue_is_private_wrap {float:right; margin-right:1em;}
424 .toggle-multiselect {background: url(../images/bullet_toggle_plus.png) no-repeat 0% 40%; padding-left:16px; margin-left:0; margin-right:5px; cursor:pointer;}
426 .toggle-multiselect {background: url(../images/bullet_toggle_plus.png) no-repeat 0% 40%; padding-left:16px; margin-left:0; margin-right:5px; cursor:pointer;}
425 .buttons { font-size: 0.9em; margin-bottom: 1.4em; margin-top: 1em; }
427 .buttons { font-size: 0.9em; margin-bottom: 1.4em; margin-top: 1em; }
426
428
427 div#issue-changesets {float:right; width:45%; margin-left: 1em; margin-bottom: 1em; background: #fff; padding-left: 1em; font-size: 90%;}
429 div#issue-changesets {float:right; width:45%; margin-left: 1em; margin-bottom: 1em; background: #fff; padding-left: 1em; font-size: 90%;}
428 div#issue-changesets div.changeset { padding: 4px;}
430 div#issue-changesets div.changeset { padding: 4px;}
429 div#issue-changesets div.changeset { border-bottom: 1px solid #ddd; }
431 div#issue-changesets div.changeset { border-bottom: 1px solid #ddd; }
430 div#issue-changesets p { margin-top: 0; margin-bottom: 1em;}
432 div#issue-changesets p { margin-top: 0; margin-bottom: 1em;}
431
433
432 div.journal {overflow:auto;}
434 div.journal {overflow:auto;}
433 div.journal.private-notes {border-left:2px solid #d22; padding-left:4px; margin-left:-6px;}
435 div.journal.private-notes {border-left:2px solid #d22; padding-left:4px; margin-left:-6px;}
434 div.journal ul.details {color:#959595; margin-bottom: 1.5em;}
436 div.journal ul.details {color:#959595; margin-bottom: 1.5em;}
435 div.journal ul.details a {color:#70A7CD;}
437 div.journal ul.details a {color:#70A7CD;}
436 div.journal ul.details a:hover {color:#D14848;}
438 div.journal ul.details a:hover {color:#D14848;}
437
439
438 div#activity dl, #search-results { margin-left: 2em; }
440 div#activity dl, #search-results { margin-left: 2em; }
439 div#activity dd, #search-results dd { margin-bottom: 1em; padding-left: 18px; font-size: 0.9em; }
441 div#activity dd, #search-results dd { margin-bottom: 1em; padding-left: 18px; font-size: 0.9em; }
440 div#activity dt, #search-results dt { margin-bottom: 0px; padding-left: 20px; line-height: 18px; background-position: 0 50%; background-repeat: no-repeat; }
442 div#activity dt, #search-results dt { margin-bottom: 0px; padding-left: 20px; line-height: 18px; background-position: 0 50%; background-repeat: no-repeat; }
441 div#activity dt.me .time { border-bottom: 1px solid #999; }
443 div#activity dt.me .time { border-bottom: 1px solid #999; }
442 div#activity dt .time { color: #777; font-size: 80%; }
444 div#activity dt .time { color: #777; font-size: 80%; }
443 div#activity dd .description, #search-results dd .description { font-style: italic; }
445 div#activity dd .description, #search-results dd .description { font-style: italic; }
444 div#activity span.project:after, #search-results span.project:after { content: " -"; }
446 div#activity span.project:after, #search-results span.project:after { content: " -"; }
445 div#activity dd span.description, #search-results dd span.description { display:block; color: #808080; }
447 div#activity dd span.description, #search-results dd span.description { display:block; color: #808080; }
446 div#activity dt.grouped {margin-left:5em;}
448 div#activity dt.grouped {margin-left:5em;}
447 div#activity dd.grouped {margin-left:9em;}
449 div#activity dd.grouped {margin-left:9em;}
448
450
449 #search-results dd { margin-bottom: 1em; padding-left: 20px; margin-left:0px; }
451 #search-results dd { margin-bottom: 1em; padding-left: 20px; margin-left:0px; }
450
452
451 div#search-results-counts {float:right;}
453 div#search-results-counts {float:right;}
452 div#search-results-counts ul { margin-top: 0.5em; }
454 div#search-results-counts ul { margin-top: 0.5em; }
453 div#search-results-counts li { list-style-type:none; float: left; margin-left: 1em; }
455 div#search-results-counts li { list-style-type:none; float: left; margin-left: 1em; }
454
456
455 dt.issue { background-image: url(../images/ticket.png); }
457 dt.issue { background-image: url(../images/ticket.png); }
456 dt.issue-edit { background-image: url(../images/ticket_edit.png); }
458 dt.issue-edit { background-image: url(../images/ticket_edit.png); }
457 dt.issue-closed { background-image: url(../images/ticket_checked.png); }
459 dt.issue-closed { background-image: url(../images/ticket_checked.png); }
458 dt.issue-note { background-image: url(../images/ticket_note.png); }
460 dt.issue-note { background-image: url(../images/ticket_note.png); }
459 dt.changeset { background-image: url(../images/changeset.png); }
461 dt.changeset { background-image: url(../images/changeset.png); }
460 dt.news { background-image: url(../images/news.png); }
462 dt.news { background-image: url(../images/news.png); }
461 dt.message { background-image: url(../images/message.png); }
463 dt.message { background-image: url(../images/message.png); }
462 dt.reply { background-image: url(../images/comments.png); }
464 dt.reply { background-image: url(../images/comments.png); }
463 dt.wiki-page { background-image: url(../images/wiki_edit.png); }
465 dt.wiki-page { background-image: url(../images/wiki_edit.png); }
464 dt.attachment { background-image: url(../images/attachment.png); }
466 dt.attachment { background-image: url(../images/attachment.png); }
465 dt.document { background-image: url(../images/document.png); }
467 dt.document { background-image: url(../images/document.png); }
466 dt.project { background-image: url(../images/projects.png); }
468 dt.project { background-image: url(../images/projects.png); }
467 dt.time-entry { background-image: url(../images/time.png); }
469 dt.time-entry { background-image: url(../images/time.png); }
468
470
469 #search-results dt.issue.closed { background-image: url(../images/ticket_checked.png); }
471 #search-results dt.issue.closed { background-image: url(../images/ticket_checked.png); }
470
472
471 div#roadmap .related-issues { margin-bottom: 1em; }
473 div#roadmap .related-issues { margin-bottom: 1em; }
472 div#roadmap .related-issues td.checkbox { display: none; }
474 div#roadmap .related-issues td.checkbox { display: none; }
473 div#roadmap .wiki h1:first-child { display: none; }
475 div#roadmap .wiki h1:first-child { display: none; }
474 div#roadmap .wiki h1 { font-size: 120%; }
476 div#roadmap .wiki h1 { font-size: 120%; }
475 div#roadmap .wiki h2 { font-size: 110%; }
477 div#roadmap .wiki h2 { font-size: 110%; }
476 body.controller-versions.action-show div#roadmap .related-issues {width:70%;}
478 body.controller-versions.action-show div#roadmap .related-issues {width:70%;}
477
479
478 div#version-summary { float:right; width:28%; margin-left: 16px; margin-bottom: 16px; background-color: #fff; }
480 div#version-summary { float:right; width:28%; margin-left: 16px; margin-bottom: 16px; background-color: #fff; }
479 div#version-summary fieldset { margin-bottom: 1em; }
481 div#version-summary fieldset { margin-bottom: 1em; }
480 div#version-summary fieldset.time-tracking table { width:100%; }
482 div#version-summary fieldset.time-tracking table { width:100%; }
481 div#version-summary th, div#version-summary td.total-hours { text-align: right; }
483 div#version-summary th, div#version-summary td.total-hours { text-align: right; }
482
484
483 table#time-report td.hours, table#time-report th.period, table#time-report th.total { text-align: right; padding-right: 0.5em; }
485 table#time-report td.hours, table#time-report th.period, table#time-report th.total { text-align: right; padding-right: 0.5em; }
484 table#time-report tbody tr.subtotal { font-style: italic; color:#777;}
486 table#time-report tbody tr.subtotal { font-style: italic; color:#777;}
485 table#time-report tbody tr.subtotal td.hours { color:#b0b0b0; }
487 table#time-report tbody tr.subtotal td.hours { color:#b0b0b0; }
486 table#time-report tbody tr.total { font-weight: bold; background-color:#EEEEEE; border-top:1px solid #e4e4e4;}
488 table#time-report tbody tr.total { font-weight: bold; background-color:#EEEEEE; border-top:1px solid #e4e4e4;}
487 table#time-report .hours-dec { font-size: 0.9em; }
489 table#time-report .hours-dec { font-size: 0.9em; }
488
490
489 div.wiki-page .contextual a {opacity: 0.4}
491 div.wiki-page .contextual a {opacity: 0.4}
490 div.wiki-page .contextual a:hover {opacity: 1}
492 div.wiki-page .contextual a:hover {opacity: 1}
491
493
492 form .attributes select { width: 60%; }
494 form .attributes select { width: 60%; }
493 form .attributes select + a.icon-only { vertical-align: middle; margin-left: 4px; }
495 form .attributes select + a.icon-only { vertical-align: middle; margin-left: 4px; }
494 input#issue_subject, input#document_title { width: 99%; }
496 input#issue_subject, input#document_title { width: 99%; }
495 select#issue_done_ratio { width: 95px; }
497 select#issue_done_ratio { width: 95px; }
496
498
497 ul.projects {margin:0; padding-left:1em;}
499 ul.projects {margin:0; padding-left:1em;}
498 ul.projects ul {padding-left:1.6em;}
500 ul.projects ul {padding-left:1.6em;}
499 ul.projects.root {margin:0; padding:0;}
501 ul.projects.root {margin:0; padding:0;}
500 ul.projects li {list-style-type:none;}
502 ul.projects li {list-style-type:none;}
501
503
502 #projects-index ul.projects ul.projects { border-left: 3px solid #e0e0e0; padding-left:1em;}
504 #projects-index ul.projects ul.projects { border-left: 3px solid #e0e0e0; padding-left:1em;}
503 #projects-index ul.projects li.root {margin-bottom: 1em;}
505 #projects-index ul.projects li.root {margin-bottom: 1em;}
504 #projects-index ul.projects li.child {margin-top: 1em;}
506 #projects-index ul.projects li.child {margin-top: 1em;}
505 #projects-index ul.projects div.root a.project { font-family: "Trebuchet MS", Verdana, sans-serif; font-weight: bold; font-size: 16px; margin: 0 0 10px 0; }
507 #projects-index ul.projects div.root a.project { font-family: "Trebuchet MS", Verdana, sans-serif; font-weight: bold; font-size: 16px; margin: 0 0 10px 0; }
506 .my-project { padding-left: 18px; background: url(../images/fav.png) no-repeat 0 50%; }
508 .my-project { padding-left: 18px; background: url(../images/fav.png) no-repeat 0 50%; }
507
509
508 #notified-projects>ul, #tracker_project_ids>ul, #custom_field_project_ids>ul {max-height:250px; overflow-y:auto;}
510 #notified-projects>ul, #tracker_project_ids>ul, #custom_field_project_ids>ul {max-height:250px; overflow-y:auto;}
509
511
510 #related-issues li img {vertical-align:middle;}
512 #related-issues li img {vertical-align:middle;}
511
513
512 ul.properties {padding:0; font-size: 0.9em; color: #777;}
514 ul.properties {padding:0; font-size: 0.9em; color: #777;}
513 ul.properties li {list-style-type:none;}
515 ul.properties li {list-style-type:none;}
514 ul.properties li span {font-style:italic;}
516 ul.properties li span {font-style:italic;}
515
517
516 .total-hours { font-size: 110%; font-weight: bold; }
518 .total-hours { font-size: 110%; font-weight: bold; }
517 .total-hours span.hours-int { font-size: 120%; }
519 .total-hours span.hours-int { font-size: 120%; }
518
520
519 .autoscroll {overflow-x: auto; padding:1px; margin-bottom: 1.2em; position: relative;}
521 .autoscroll {overflow-x: auto; padding:1px; margin-bottom: 1.2em; position: relative;}
520 #user_login, #user_firstname, #user_lastname, #user_mail, #my_account_form select, #user_form select, #user_identity_url { width: 90%; }
522 #user_login, #user_firstname, #user_lastname, #user_mail, #my_account_form select, #user_form select, #user_identity_url { width: 90%; }
521
523
522 #workflow_copy_form select { width: 200px; }
524 #workflow_copy_form select { width: 200px; }
523 table.transitions td.enabled {background: #bfb;}
525 table.transitions td.enabled {background: #bfb;}
524 #workflow_form table select {font-size:90%; max-width:100px;}
526 #workflow_form table select {font-size:90%; max-width:100px;}
525 table.fields_permissions td.readonly {background:#ddd;}
527 table.fields_permissions td.readonly {background:#ddd;}
526 table.fields_permissions td.required {background:#d88;}
528 table.fields_permissions td.required {background:#d88;}
527
529
528 select.expandable {vertical-align:top;}
530 select.expandable {vertical-align:top;}
529
531
530 textarea#custom_field_possible_values {width: 95%; resize:vertical}
532 textarea#custom_field_possible_values {width: 95%; resize:vertical}
531 textarea#custom_field_default_value {width: 95%; resize:vertical}
533 textarea#custom_field_default_value {width: 95%; resize:vertical}
532 .sort-handle {display:inline-block; vertical-align:middle;}
534 .sort-handle {display:inline-block; vertical-align:middle;}
533
535
534 input#content_comments {width: 99%}
536 input#content_comments {width: 99%}
535
537
536 span.pagination {margin-left:3px; color:#888; display:block;}
538 span.pagination {margin-left:3px; color:#888; display:block;}
537 .pagination ul.pages {
539 .pagination ul.pages {
538 margin: 0 5px 0 0;
540 margin: 0 5px 0 0;
539 padding: 0;
541 padding: 0;
540 display: inline;
542 display: inline;
541 }
543 }
542 .pagination ul.pages li {
544 .pagination ul.pages li {
543 display: inline-block;
545 display: inline-block;
544 padding: 0;
546 padding: 0;
545 border: 1px solid #ddd;
547 border: 1px solid #ddd;
546 margin-left: -1px;
548 margin-left: -1px;
547 line-height: 2em;
549 line-height: 2em;
548 margin-bottom: 1em;
550 margin-bottom: 1em;
549 white-space: nowrap;
551 white-space: nowrap;
550 text-align: center;
552 text-align: center;
551 }
553 }
552 .pagination ul.pages li a,
554 .pagination ul.pages li a,
553 .pagination ul.pages li span {
555 .pagination ul.pages li span {
554 padding: 3px 8px;
556 padding: 3px 8px;
555 }
557 }
556 .pagination ul.pages li:first-child {
558 .pagination ul.pages li:first-child {
557 border-top-left-radius: 4px;
559 border-top-left-radius: 4px;
558 border-bottom-left-radius: 4px;
560 border-bottom-left-radius: 4px;
559 }
561 }
560 .pagination ul.pages li:last-child {
562 .pagination ul.pages li:last-child {
561 border-top-right-radius: 4px;
563 border-top-right-radius: 4px;
562 border-bottom-right-radius: 4px;
564 border-bottom-right-radius: 4px;
563 }
565 }
564 .pagination ul.pages li.current {
566 .pagination ul.pages li.current {
565 color: white;
567 color: white;
566 background-color: #628DB6;
568 background-color: #628DB6;
567 border-color: #628DB6;
569 border-color: #628DB6;
568 }
570 }
569 .pagination ul.pages li.page:hover {
571 .pagination ul.pages li.page:hover {
570 background-color: #ddd;
572 background-color: #ddd;
571 }
573 }
572 .pagination ul.pages li.page a:hover,
574 .pagination ul.pages li.page a:hover,
573 .pagination ul.pages li.page a:active {
575 .pagination ul.pages li.page a:active {
574 color: #169;
576 color: #169;
575 text-decoration: inherit;
577 text-decoration: inherit;
576 }
578 }
577 .pagination .per-page span.selected {
579 .pagination .per-page span.selected {
578 font-weight: bold;
580 font-weight: bold;
579 }
581 }
580 span.pagination>span {white-space:nowrap;}
582 span.pagination>span {white-space:nowrap;}
581
583
582 #search-form fieldset p {margin:0.2em 0;}
584 #search-form fieldset p {margin:0.2em 0;}
583
585
584 /***** Tabular forms ******/
586 /***** Tabular forms ******/
585 .tabular p{
587 .tabular p{
586 margin: 0;
588 margin: 0;
587 padding: 3px 0 3px 0;
589 padding: 3px 0 3px 0;
588 padding-left: 180px; /* width of left column containing the label elements */
590 padding-left: 180px; /* width of left column containing the label elements */
589 min-height: 1.8em;
591 min-height: 1.8em;
590 clear:left;
592 clear:left;
591 }
593 }
592
594
593 html>body .tabular p {overflow:hidden;}
595 html>body .tabular p {overflow:hidden;}
594
596
595 .tabular input, .tabular select {max-width:95%}
597 .tabular input, .tabular select {max-width:95%}
596 .tabular textarea {width:95%; resize:vertical;}
598 .tabular textarea {width:95%; resize:vertical;}
597
599
598 .tabular label{
600 .tabular label{
599 font-weight: bold;
601 font-weight: bold;
600 float: left;
602 float: left;
601 text-align: right;
603 text-align: right;
602 /* width of left column */
604 /* width of left column */
603 margin-left: -180px;
605 margin-left: -180px;
604 /* width of labels. Should be smaller than left column to create some right margin */
606 /* width of labels. Should be smaller than left column to create some right margin */
605 width: 175px;
607 width: 175px;
606 }
608 }
607
609
608 .tabular label.floating{
610 .tabular label.floating{
609 font-weight: normal;
611 font-weight: normal;
610 margin-left: 0px;
612 margin-left: 0px;
611 text-align: left;
613 text-align: left;
612 width: 270px;
614 width: 270px;
613 }
615 }
614
616
615 .tabular label.block{
617 .tabular label.block{
616 font-weight: normal;
618 font-weight: normal;
617 margin-left: 0px !important;
619 margin-left: 0px !important;
618 text-align: left;
620 text-align: left;
619 float: none;
621 float: none;
620 display: block;
622 display: block;
621 width: auto !important;
623 width: auto !important;
622 }
624 }
623
625
624 .tabular label.inline{
626 .tabular label.inline{
625 font-weight: normal;
627 font-weight: normal;
626 float:none;
628 float:none;
627 margin-left: 5px !important;
629 margin-left: 5px !important;
628 width: auto;
630 width: auto;
629 }
631 }
630
632
631 label.no-css {
633 label.no-css {
632 font-weight: inherit;
634 font-weight: inherit;
633 float:none;
635 float:none;
634 text-align:left;
636 text-align:left;
635 margin-left:0px;
637 margin-left:0px;
636 width:auto;
638 width:auto;
637 }
639 }
638 input#time_entry_comments { width: 90%;}
640 input#time_entry_comments { width: 90%;}
639
641
640 #preview fieldset {margin-top: 1em; background: url(../images/draft.png)}
642 #preview fieldset {margin-top: 1em; background: url(../images/draft.png)}
641
643
642 .tabular.settings p{ padding-left: 300px; }
644 .tabular.settings p{ padding-left: 300px; }
643 .tabular.settings label{ margin-left: -300px; width: 295px; }
645 .tabular.settings label{ margin-left: -300px; width: 295px; }
644 .tabular.settings textarea { width: 99%; }
646 .tabular.settings textarea { width: 99%; }
645
647
646 .settings.enabled_scm table {width:100%}
648 .settings.enabled_scm table {width:100%}
647 .settings.enabled_scm td.scm_name{ font-weight: bold; }
649 .settings.enabled_scm td.scm_name{ font-weight: bold; }
648
650
649 fieldset.settings label { display: block; }
651 fieldset.settings label { display: block; }
650 fieldset#notified_events .parent { padding-left: 20px; }
652 fieldset#notified_events .parent { padding-left: 20px; }
651
653
652 span.required {color: #bb0000;}
654 span.required {color: #bb0000;}
653 .summary {font-style: italic;}
655 .summary {font-style: italic;}
654
656
655 .check_box_group {
657 .check_box_group {
656 display:block;
658 display:block;
657 width:95%;
659 width:95%;
658 max-height:300px;
660 max-height:300px;
659 overflow-y:auto;
661 overflow-y:auto;
660 padding:2px 4px 4px 2px;
662 padding:2px 4px 4px 2px;
661 background:#fff;
663 background:#fff;
662 border:1px solid #9EB1C2;
664 border:1px solid #9EB1C2;
663 border-radius:2px
665 border-radius:2px
664 }
666 }
665 .check_box_group label {
667 .check_box_group label {
666 font-weight: normal;
668 font-weight: normal;
667 margin-left: 0px !important;
669 margin-left: 0px !important;
668 text-align: left;
670 text-align: left;
669 float: none;
671 float: none;
670 display: block;
672 display: block;
671 width: auto;
673 width: auto;
672 }
674 }
673 .check_box_group.bool_cf {border:0; background:inherit;}
675 .check_box_group.bool_cf {border:0; background:inherit;}
674 .check_box_group.bool_cf label {display: inline;}
676 .check_box_group.bool_cf label {display: inline;}
675
677
676 #attachments_fields input.description, #existing-attachments input.description {margin-left:4px; width:340px;}
678 #attachments_fields input.description, #existing-attachments input.description {margin-left:4px; width:340px;}
677 #attachments_fields>span, #existing-attachments>span {display:block; white-space:nowrap;}
679 #attachments_fields>span, #existing-attachments>span {display:block; white-space:nowrap;}
678 #attachments_fields input.filename, #existing-attachments .filename {border:0; width:250px; color:#555; background-color:inherit; background:url(../images/attachment.png) no-repeat 1px 50%; padding-left:18px;}
680 #attachments_fields input.filename, #existing-attachments .filename {border:0; width:250px; color:#555; background-color:inherit; background:url(../images/attachment.png) no-repeat 1px 50%; padding-left:18px;}
679 #attachments_fields input.filename {height:1.8em;}
681 #attachments_fields input.filename {height:1.8em;}
680 #attachments_fields .ajax-waiting input.filename {background:url(../images/hourglass.png) no-repeat 0px 50%;}
682 #attachments_fields .ajax-waiting input.filename {background:url(../images/hourglass.png) no-repeat 0px 50%;}
681 #attachments_fields .ajax-loading input.filename {background:url(../images/loading.gif) no-repeat 0px 50%;}
683 #attachments_fields .ajax-loading input.filename {background:url(../images/loading.gif) no-repeat 0px 50%;}
682 #attachments_fields div.ui-progressbar { width: 100px; height:14px; margin: 2px 0 -5px 8px; display: inline-block; }
684 #attachments_fields div.ui-progressbar { width: 100px; height:14px; margin: 2px 0 -5px 8px; display: inline-block; }
683 a.remove-upload {background: url(../images/delete.png) no-repeat 1px 50%; width:1px; display:inline-block; padding-left:16px;}
685 a.remove-upload {background: url(../images/delete.png) no-repeat 1px 50%; width:1px; display:inline-block; padding-left:16px;}
684 a.remove-upload:hover {text-decoration:none !important;}
686 a.remove-upload:hover {text-decoration:none !important;}
685 .existing-attachment.deleted .filename {text-decoration:line-through; color:#999 !important;}
687 .existing-attachment.deleted .filename {text-decoration:line-through; color:#999 !important;}
686
688
687 div.fileover { background-color: lavender; }
689 div.fileover { background-color: lavender; }
688
690
689 div.attachments { margin: 12px 0; }
691 div.attachments { margin: 12px 0; }
690 div.attachments p { margin:4px 0 2px 0; }
692 div.attachments p { margin:4px 0 2px 0; }
691 div.attachments img { vertical-align: middle; }
693 div.attachments img { vertical-align: middle; }
692 div.attachments span.author { font-size: 0.9em; color: #888; }
694 div.attachments span.author { font-size: 0.9em; color: #888; }
693
695
694 div.thumbnails {margin:0.6em;}
696 div.thumbnails {margin:0.6em;}
695 div.thumbnails div {background:#fff;border:2px solid #ddd;display:inline-block;margin-right:2px;}
697 div.thumbnails div {background:#fff;border:2px solid #ddd;display:inline-block;margin-right:2px;}
696 div.thumbnails img {margin: 3px; vertical-align: middle;}
698 div.thumbnails img {margin: 3px; vertical-align: middle;}
697 #history div.thumbnails {margin-left: 2em;}
699 #history div.thumbnails {margin-left: 2em;}
698
700
699 p.other-formats { text-align: right; font-size:0.9em; color: #666; }
701 p.other-formats { text-align: right; font-size:0.9em; color: #666; }
700 .other-formats span + span:before { content: "| "; }
702 .other-formats span + span:before { content: "| "; }
701
703
702 a.atom { background: url(../images/feed.png) no-repeat 1px 50%; padding: 2px 0px 3px 16px; }
704 a.atom { background: url(../images/feed.png) no-repeat 1px 50%; padding: 2px 0px 3px 16px; }
703
705
704 em.info {font-style:normal;font-size:90%;color:#888;display:block;}
706 em.info {font-style:normal;font-size:90%;color:#888;display:block;}
705 em.info.error {padding-left:20px; background:url(../images/exclamation.png) no-repeat 0 50%;}
707 em.info.error {padding-left:20px; background:url(../images/exclamation.png) no-repeat 0 50%;}
706
708
707 textarea.text_cf {width:95%; resize:vertical;}
709 textarea.text_cf {width:95%; resize:vertical;}
708 input.string_cf, input.link_cf {width:95%;}
710 input.string_cf, input.link_cf {width:95%;}
709 select.bool_cf {width:auto !important;}
711 select.bool_cf {width:auto !important;}
710
712
711 #tab-content-modules fieldset p {margin:3px 0 4px 0;}
713 #tab-content-modules fieldset p {margin:3px 0 4px 0;}
712
714
713 #tab-content-users .splitcontentleft {width: 64%;}
715 #tab-content-users .splitcontentleft {width: 64%;}
714 #tab-content-users .splitcontentright {width: 34%;}
716 #tab-content-users .splitcontentright {width: 34%;}
715 #tab-content-users fieldset {padding:1em; margin-bottom: 1em;}
717 #tab-content-users fieldset {padding:1em; margin-bottom: 1em;}
716 #tab-content-users fieldset legend {font-weight: bold;}
718 #tab-content-users fieldset legend {font-weight: bold;}
717 #tab-content-users fieldset label {display: block;}
719 #tab-content-users fieldset label {display: block;}
718 #tab-content-users #principals {max-height: 400px; overflow: auto;}
720 #tab-content-users #principals {max-height: 400px; overflow: auto;}
719
721
720 #users_for_watcher {height: 200px; overflow:auto;}
722 #users_for_watcher {height: 200px; overflow:auto;}
721 #users_for_watcher label {display: block;}
723 #users_for_watcher label {display: block;}
722
724
723 table.members td.name {padding-left: 20px;}
725 table.members td.name {padding-left: 20px;}
724 table.members td.group, table.members td.groupnonmember, table.members td.groupanonymous {background: url(../images/group.png) no-repeat 0% 1px;}
726 table.members td.group, table.members td.groupnonmember, table.members td.groupanonymous {background: url(../images/group.png) no-repeat 0% 1px;}
725
727
726 input#principal_search, input#user_search {width:90%}
728 input#principal_search, input#user_search {width:90%}
727 .roles-selection label {display:inline-block; width:210px;}
729 .roles-selection label {display:inline-block; width:210px;}
728
730
729 input.autocomplete {
731 input.autocomplete {
730 background: #fff url(../images/magnifier.png) no-repeat 2px 50%; padding-left:20px !important;
732 background: #fff url(../images/magnifier.png) no-repeat 2px 50%; padding-left:20px !important;
731 border:1px solid #9EB1C2; border-radius:2px; height:1.5em;
733 border:1px solid #9EB1C2; border-radius:2px; height:1.5em;
732 }
734 }
733 input.autocomplete.ajax-loading {
735 input.autocomplete.ajax-loading {
734 background-image: url(../images/loading.gif);
736 background-image: url(../images/loading.gif);
735 }
737 }
736
738
737 .role-visibility {padding-left:2em;}
739 .role-visibility {padding-left:2em;}
738
740
739 .objects-selection {
741 .objects-selection {
740 height: 300px;
742 height: 300px;
741 overflow: auto;
743 overflow: auto;
742 margin-bottom: 1em;
744 margin-bottom: 1em;
743 }
745 }
744
746
745 .objects-selection label {
747 .objects-selection label {
746 display: block;
748 display: block;
747 }
749 }
748
750
749 .objects-selection>div {
751 .objects-selection>div {
750 column-count: auto;
752 column-count: auto;
751 column-width: 200px;
753 column-width: 200px;
752 -webkit-column-count: auto;
754 -webkit-column-count: auto;
753 -webkit-column-width: 200px;
755 -webkit-column-width: 200px;
754 -webkit-column-gap : 0.5rem;
756 -webkit-column-gap : 0.5rem;
755 -webkit-column-rule: 1px solid #ccc;
757 -webkit-column-rule: 1px solid #ccc;
756 -moz-column-count: auto;
758 -moz-column-count: auto;
757 -moz-column-width: 200px;
759 -moz-column-width: 200px;
758 -moz-column-gap : 0.5rem;
760 -moz-column-gap : 0.5rem;
759 -moz-column-rule: 1px solid #ccc;
761 -moz-column-rule: 1px solid #ccc;
760 }
762 }
761
763
762 /***** Flash & error messages ****/
764 /***** Flash & error messages ****/
763 #errorExplanation, div.flash, .nodata, .warning, .conflict {
765 #errorExplanation, div.flash, .nodata, .warning, .conflict {
764 padding: 6px 4px 6px 30px;
766 padding: 6px 4px 6px 30px;
765 margin-bottom: 12px;
767 margin-bottom: 12px;
766 font-size: 1.1em;
768 font-size: 1.1em;
767 border: 1px solid;
769 border: 1px solid;
768 border-radius: 3px;
770 border-radius: 3px;
769 }
771 }
770
772
771 div.flash {margin-top: 8px;}
773 div.flash {margin-top: 8px;}
772
774
773 div.flash.error, #errorExplanation {
775 div.flash.error, #errorExplanation {
774 background: url(../images/exclamation.png) 8px 50% no-repeat;
776 background: url(../images/exclamation.png) 8px 50% no-repeat;
775 background-color: #ffe3e3;
777 background-color: #ffe3e3;
776 border-color: #d88;
778 border-color: #d88;
777 color: #880000;
779 color: #880000;
778 }
780 }
779
781
780 div.flash.notice {
782 div.flash.notice {
781 background: url(../images/true.png) 8px 5px no-repeat;
783 background: url(../images/true.png) 8px 5px no-repeat;
782 background-color: #dfffdf;
784 background-color: #dfffdf;
783 border-color: #9fcf9f;
785 border-color: #9fcf9f;
784 color: #005f00;
786 color: #005f00;
785 }
787 }
786
788
787 div.flash.warning, .conflict {
789 div.flash.warning, .conflict {
788 background: url(../images/warning.png) 8px 5px no-repeat;
790 background: url(../images/warning.png) 8px 5px no-repeat;
789 background-color: #F3EDD1;
791 background-color: #F3EDD1;
790 border-color: #eadbbc;
792 border-color: #eadbbc;
791 color: #A6750C;
793 color: #A6750C;
792 text-align: left;
794 text-align: left;
793 }
795 }
794
796
795 .nodata, .warning {
797 .nodata, .warning {
796 text-align: center;
798 text-align: center;
797 background-color: #F3EDD1;
799 background-color: #F3EDD1;
798 border-color: #eadbbc;
800 border-color: #eadbbc;
799 color: #A6750C;
801 color: #A6750C;
800 }
802 }
801
803
802 #errorExplanation ul { font-size: 0.9em;}
804 #errorExplanation ul { font-size: 0.9em;}
803 #errorExplanation h2, #errorExplanation p { display: none; }
805 #errorExplanation h2, #errorExplanation p { display: none; }
804
806
805 .conflict-details {font-size:80%;}
807 .conflict-details {font-size:80%;}
806
808
807 /***** Ajax indicator ******/
809 /***** Ajax indicator ******/
808 #ajax-indicator {
810 #ajax-indicator {
809 position: absolute; /* fixed not supported by IE */
811 position: absolute; /* fixed not supported by IE */
810 background-color:#eee;
812 background-color:#eee;
811 border: 1px solid #bbb;
813 border: 1px solid #bbb;
812 top:35%;
814 top:35%;
813 left:40%;
815 left:40%;
814 width:20%;
816 width:20%;
815 font-weight:bold;
817 font-weight:bold;
816 text-align:center;
818 text-align:center;
817 padding:0.6em;
819 padding:0.6em;
818 z-index:100;
820 z-index:100;
819 opacity: 0.5;
821 opacity: 0.5;
820 }
822 }
821
823
822 html>body #ajax-indicator { position: fixed; }
824 html>body #ajax-indicator { position: fixed; }
823
825
824 #ajax-indicator span {
826 #ajax-indicator span {
825 background-position: 0% 40%;
827 background-position: 0% 40%;
826 background-repeat: no-repeat;
828 background-repeat: no-repeat;
827 background-image: url(../images/loading.gif);
829 background-image: url(../images/loading.gif);
828 padding-left: 26px;
830 padding-left: 26px;
829 vertical-align: bottom;
831 vertical-align: bottom;
830 }
832 }
831
833
832 /***** Calendar *****/
834 /***** Calendar *****/
833 table.cal {border-collapse: collapse; width: 100%; margin: 0px 0 6px 0;border: 1px solid #d7d7d7;}
835 table.cal {border-collapse: collapse; width: 100%; margin: 0px 0 6px 0;border: 1px solid #d7d7d7;}
834 table.cal thead th {width: 14%; background-color:#EEEEEE; padding: 4px; }
836 table.cal thead th {width: 14%; background-color:#EEEEEE; padding: 4px; }
835 table.cal thead th.week-number {width: auto;}
837 table.cal thead th.week-number {width: auto;}
836 table.cal tbody tr {height: 100px;}
838 table.cal tbody tr {height: 100px;}
837 table.cal td {border: 1px solid #d7d7d7; vertical-align: top; font-size: 0.9em;}
839 table.cal td {border: 1px solid #d7d7d7; vertical-align: top; font-size: 0.9em;}
838 table.cal td.week-number { background-color:#EEEEEE; padding: 4px; border:none; font-size: 1em;}
840 table.cal td.week-number { background-color:#EEEEEE; padding: 4px; border:none; font-size: 1em;}
839 table.cal td p.day-num {font-size: 1.1em; text-align:right;}
841 table.cal td p.day-num {font-size: 1.1em; text-align:right;}
840 table.cal td.odd p.day-num {color: #bbb;}
842 table.cal td.odd p.day-num {color: #bbb;}
841 table.cal td.today {background:#ffffdd;}
843 table.cal td.today {background:#ffffdd;}
842 table.cal td.today p.day-num {font-weight: bold;}
844 table.cal td.today p.day-num {font-weight: bold;}
843 table.cal .starting a, p.cal.legend .starting {background: url(../images/bullet_go.png) no-repeat -1px -2px; padding-left:16px;}
845 table.cal .starting a, p.cal.legend .starting {background: url(../images/bullet_go.png) no-repeat -1px -2px; padding-left:16px;}
844 table.cal .ending a, p.cal.legend .ending {background: url(../images/bullet_end.png) no-repeat -1px -2px; padding-left:16px;}
846 table.cal .ending a, p.cal.legend .ending {background: url(../images/bullet_end.png) no-repeat -1px -2px; padding-left:16px;}
845 table.cal .starting.ending a, p.cal.legend .starting.ending {background: url(../images/bullet_diamond.png) no-repeat -1px -2px; padding-left:16px;}
847 table.cal .starting.ending a, p.cal.legend .starting.ending {background: url(../images/bullet_diamond.png) no-repeat -1px -2px; padding-left:16px;}
846 p.cal.legend span {display:block;}
848 p.cal.legend span {display:block;}
847
849
848 /***** Tooltips ******/
850 /***** Tooltips ******/
849 .tooltip{position:relative;z-index:24;}
851 .tooltip{position:relative;z-index:24;}
850 .tooltip:hover{z-index:25;color:#000;}
852 .tooltip:hover{z-index:25;color:#000;}
851 .tooltip span.tip{display: none; text-align:left;}
853 .tooltip span.tip{display: none; text-align:left;}
852
854
853 div.tooltip:hover span.tip{
855 div.tooltip:hover span.tip{
854 display:block;
856 display:block;
855 position:absolute;
857 position:absolute;
856 top:12px; width:270px;
858 top:12px; width:270px;
857 border:1px solid #555;
859 border:1px solid #555;
858 background-color:#fff;
860 background-color:#fff;
859 padding: 4px;
861 padding: 4px;
860 font-size: 0.8em;
862 font-size: 0.8em;
861 color:#505050;
863 color:#505050;
862 }
864 }
863
865
864 img.ui-datepicker-trigger {
866 img.ui-datepicker-trigger {
865 cursor: pointer;
867 cursor: pointer;
866 vertical-align: middle;
868 vertical-align: middle;
867 margin-left: 4px;
869 margin-left: 4px;
868 }
870 }
869
871
870 /***** Progress bar *****/
872 /***** Progress bar *****/
871 table.progress {
873 table.progress {
872 border-collapse: collapse;
874 border-collapse: collapse;
873 border-spacing: 0pt;
875 border-spacing: 0pt;
874 empty-cells: show;
876 empty-cells: show;
875 text-align: center;
877 text-align: center;
876 float:left;
878 float:left;
877 margin: 1px 6px 1px 0px;
879 margin: 1px 6px 1px 0px;
878 }
880 }
879
881
880 table.progress {width:80px;}
882 table.progress {width:80px;}
881 table.progress td { height: 1em; }
883 table.progress td { height: 1em; }
882 table.progress td.closed { background: #BAE0BA none repeat scroll 0%; }
884 table.progress td.closed { background: #BAE0BA none repeat scroll 0%; }
883 table.progress td.done { background: #D3EDD3 none repeat scroll 0%; }
885 table.progress td.done { background: #D3EDD3 none repeat scroll 0%; }
884 table.progress td.todo { background: #eee none repeat scroll 0%; }
886 table.progress td.todo { background: #eee none repeat scroll 0%; }
885 p.percent {font-size: 80%; margin:0;}
887 p.percent {font-size: 80%; margin:0;}
886 p.progress-info {clear: left; font-size: 80%; margin-top:-4px; color:#777;}
888 p.progress-info {clear: left; font-size: 80%; margin-top:-4px; color:#777;}
887
889
888 .version-overview table.progress {width:40em;}
890 .version-overview table.progress {width:40em;}
889 .version-overview table.progress td { height: 1.2em; }
891 .version-overview table.progress td { height: 1.2em; }
890
892
891 /***** Tabs *****/
893 /***** Tabs *****/
892 #content .tabs {height: 2.6em; margin-bottom:1.2em; position:relative; overflow:hidden;}
894 #content .tabs {height: 2.6em; margin-bottom:1.2em; position:relative; overflow:hidden;}
893 #content .tabs ul {margin:0; position:absolute; bottom:0; padding-left:0.5em; width: 2000px; border-bottom: 1px solid #bbbbbb;}
895 #content .tabs ul {margin:0; position:absolute; bottom:0; padding-left:0.5em; width: 2000px; border-bottom: 1px solid #bbbbbb;}
894 #content .tabs ul li {
896 #content .tabs ul li {
895 float:left;
897 float:left;
896 list-style-type:none;
898 list-style-type:none;
897 white-space:nowrap;
899 white-space:nowrap;
898 margin-right:4px;
900 margin-right:4px;
899 background:#fff;
901 background:#fff;
900 position:relative;
902 position:relative;
901 margin-bottom:-1px;
903 margin-bottom:-1px;
902 }
904 }
903 #content .tabs ul li a{
905 #content .tabs ul li a{
904 display:block;
906 display:block;
905 font-size: 0.9em;
907 font-size: 0.9em;
906 text-decoration:none;
908 text-decoration:none;
907 line-height:1.3em;
909 line-height:1.3em;
908 padding:4px 6px 4px 6px;
910 padding:4px 6px 4px 6px;
909 border: 1px solid #ccc;
911 border: 1px solid #ccc;
910 border-bottom: 1px solid #bbbbbb;
912 border-bottom: 1px solid #bbbbbb;
911 background-color: #f6f6f6;
913 background-color: #f6f6f6;
912 color:#999;
914 color:#999;
913 font-weight:bold;
915 font-weight:bold;
914 border-top-left-radius:3px;
916 border-top-left-radius:3px;
915 border-top-right-radius:3px;
917 border-top-right-radius:3px;
916 }
918 }
917
919
918 #content .tabs ul li a:hover {
920 #content .tabs ul li a:hover {
919 background-color: #ffffdd;
921 background-color: #ffffdd;
920 text-decoration:none;
922 text-decoration:none;
921 }
923 }
922
924
923 #content .tabs ul li a.selected {
925 #content .tabs ul li a.selected {
924 background-color: #fff;
926 background-color: #fff;
925 border: 1px solid #bbbbbb;
927 border: 1px solid #bbbbbb;
926 border-bottom: 1px solid #fff;
928 border-bottom: 1px solid #fff;
927 color:#444;
929 color:#444;
928 }
930 }
929
931
930 #content .tabs ul li a.selected:hover {background-color: #fff;}
932 #content .tabs ul li a.selected:hover {background-color: #fff;}
931
933
932 div.tabs-buttons { position:absolute; right: 0; width: 54px; height: 24px; background: white; bottom: 0; border-bottom: 1px solid #bbbbbb; }
934 div.tabs-buttons { position:absolute; right: 0; width: 54px; height: 24px; background: white; bottom: 0; border-bottom: 1px solid #bbbbbb; }
933
935
934 button.tab-left, button.tab-right {
936 button.tab-left, button.tab-right {
935 font-size: 0.9em;
937 font-size: 0.9em;
936 cursor: pointer;
938 cursor: pointer;
937 height:24px;
939 height:24px;
938 border: 1px solid #ccc;
940 border: 1px solid #ccc;
939 border-bottom: 1px solid #bbbbbb;
941 border-bottom: 1px solid #bbbbbb;
940 position:absolute;
942 position:absolute;
941 padding:4px;
943 padding:4px;
942 width: 20px;
944 width: 20px;
943 bottom: -1px;
945 bottom: -1px;
944 }
946 }
945 button.tab-left:hover, button.tab-right:hover {
947 button.tab-left:hover, button.tab-right:hover {
946 background-color: #f5f5f5;
948 background-color: #f5f5f5;
947 }
949 }
948 button.tab-left:focus, button.tab-right:focus {
950 button.tab-left:focus, button.tab-right:focus {
949 outline: 0;
951 outline: 0;
950 }
952 }
951
953
952 button.tab-left {
954 button.tab-left {
953 right: 20px;
955 right: 20px;
954 background: #eeeeee url(../images/bullet_arrow_left.png) no-repeat 50% 50%;
956 background: #eeeeee url(../images/bullet_arrow_left.png) no-repeat 50% 50%;
955 border-top-left-radius:3px;
957 border-top-left-radius:3px;
956 }
958 }
957
959
958 button.tab-right {
960 button.tab-right {
959 right: 0;
961 right: 0;
960 background: #eeeeee url(../images/bullet_arrow_right.png) no-repeat 50% 50%;
962 background: #eeeeee url(../images/bullet_arrow_right.png) no-repeat 50% 50%;
961 border-top-right-radius:3px;
963 border-top-right-radius:3px;
962 }
964 }
963
965
964 button.tab-left.disabled, button.tab-right.disabled {
966 button.tab-left.disabled, button.tab-right.disabled {
965 background-color: #ccc;
967 background-color: #ccc;
966 cursor: unset;
968 cursor: unset;
967 }
969 }
968
970
969 /***** Diff *****/
971 /***** Diff *****/
970 .diff_out { background: #fcc; }
972 .diff_out { background: #fcc; }
971 .diff_out span { background: #faa; }
973 .diff_out span { background: #faa; }
972 .diff_in { background: #cfc; }
974 .diff_in { background: #cfc; }
973 .diff_in span { background: #afa; }
975 .diff_in span { background: #afa; }
974
976
975 .text-diff {
977 .text-diff {
976 padding: 1em;
978 padding: 1em;
977 background-color:#f6f6f6;
979 background-color:#f6f6f6;
978 color:#505050;
980 color:#505050;
979 border: 1px solid #e4e4e4;
981 border: 1px solid #e4e4e4;
980 }
982 }
981
983
982 /***** Wiki *****/
984 /***** Wiki *****/
983 div.wiki table {
985 div.wiki table {
984 border-collapse: collapse;
986 border-collapse: collapse;
985 margin-bottom: 1em;
987 margin-bottom: 1em;
986 }
988 }
987
989
988 div.wiki table, div.wiki td, div.wiki th {
990 div.wiki table, div.wiki td, div.wiki th {
989 border: 1px solid #bbb;
991 border: 1px solid #bbb;
990 padding: 4px;
992 padding: 4px;
991 }
993 }
992
994
993 div.wiki .noborder, div.wiki .noborder td, div.wiki .noborder th {border:0;}
995 div.wiki .noborder, div.wiki .noborder td, div.wiki .noborder th {border:0;}
994
996
995 div.wiki .external {
997 div.wiki .external {
996 background-position: 0% 60%;
998 background-position: 0% 60%;
997 background-repeat: no-repeat;
999 background-repeat: no-repeat;
998 padding-left: 12px;
1000 padding-left: 12px;
999 background-image: url(../images/external.png);
1001 background-image: url(../images/external.png);
1000 }
1002 }
1001
1003
1002 div.wiki a {word-wrap: break-word;}
1004 div.wiki a {word-wrap: break-word;}
1003 div.wiki a.new {color: #b73535;}
1005 div.wiki a.new {color: #b73535;}
1004
1006
1005 div.wiki ul, div.wiki ol {margin-bottom:1em;}
1007 div.wiki ul, div.wiki ol {margin-bottom:1em;}
1006 div.wiki li>ul, div.wiki li>ol {margin-bottom: 0;}
1008 div.wiki li>ul, div.wiki li>ol {margin-bottom: 0;}
1007
1009
1008 div.wiki pre {
1010 div.wiki pre {
1009 margin: 1em 1em 1em 1.6em;
1011 margin: 1em 1em 1em 1.6em;
1010 padding: 8px;
1012 padding: 8px;
1011 background-color: #fafafa;
1013 background-color: #fafafa;
1012 border: 1px solid #e2e2e2;
1014 border: 1px solid #e2e2e2;
1013 border-radius: 3px;
1015 border-radius: 3px;
1014 width:auto;
1016 width:auto;
1015 overflow-x: auto;
1017 overflow-x: auto;
1016 overflow-y: hidden;
1018 overflow-y: hidden;
1017 }
1019 }
1018
1020
1019 div.wiki ul.toc {
1021 div.wiki ul.toc {
1020 background-color: #ffffdd;
1022 background-color: #ffffdd;
1021 border: 1px solid #e4e4e4;
1023 border: 1px solid #e4e4e4;
1022 padding: 4px;
1024 padding: 4px;
1023 line-height: 1.2em;
1025 line-height: 1.2em;
1024 margin-bottom: 12px;
1026 margin-bottom: 12px;
1025 margin-right: 12px;
1027 margin-right: 12px;
1026 margin-left: 0;
1028 margin-left: 0;
1027 display: table
1029 display: table
1028 }
1030 }
1029 * html div.wiki ul.toc { width: 50%; } /* IE6 doesn't autosize div */
1031 * html div.wiki ul.toc { width: 50%; } /* IE6 doesn't autosize div */
1030
1032
1031 div.wiki ul.toc.right { float: right; margin-left: 12px; margin-right: 0; width: auto; }
1033 div.wiki ul.toc.right { float: right; margin-left: 12px; margin-right: 0; width: auto; }
1032 div.wiki ul.toc.left { float: left; margin-right: 12px; margin-left: 0; width: auto; }
1034 div.wiki ul.toc.left { float: left; margin-right: 12px; margin-left: 0; width: auto; }
1033 div.wiki ul.toc ul { margin: 0; padding: 0; }
1035 div.wiki ul.toc ul { margin: 0; padding: 0; }
1034 div.wiki ul.toc li {list-style-type:none; margin: 0; font-size:12px;}
1036 div.wiki ul.toc li {list-style-type:none; margin: 0; font-size:12px;}
1035 div.wiki ul.toc li li {margin-left: 1.5em; font-size:10px;}
1037 div.wiki ul.toc li li {margin-left: 1.5em; font-size:10px;}
1036 div.wiki ul.toc a {
1038 div.wiki ul.toc a {
1037 font-size: 0.9em;
1039 font-size: 0.9em;
1038 font-weight: normal;
1040 font-weight: normal;
1039 text-decoration: none;
1041 text-decoration: none;
1040 color: #606060;
1042 color: #606060;
1041 }
1043 }
1042 div.wiki ul.toc a:hover { color: #c61a1a; text-decoration: underline;}
1044 div.wiki ul.toc a:hover { color: #c61a1a; text-decoration: underline;}
1043
1045
1044 a.wiki-anchor { display: none; margin-left: 6px; text-decoration: none; }
1046 a.wiki-anchor { display: none; margin-left: 6px; text-decoration: none; }
1045 a.wiki-anchor:hover { color: #aaa !important; text-decoration: none; }
1047 a.wiki-anchor:hover { color: #aaa !important; text-decoration: none; }
1046 h1:hover a.wiki-anchor, h2:hover a.wiki-anchor, h3:hover a.wiki-anchor { display: inline; color: #ddd; }
1048 h1:hover a.wiki-anchor, h2:hover a.wiki-anchor, h3:hover a.wiki-anchor { display: inline; color: #ddd; }
1047
1049
1048 div.wiki img {vertical-align:middle; max-width:100%;}
1050 div.wiki img {vertical-align:middle; max-width:100%;}
1049
1051
1050 /***** My page layout *****/
1052 /***** My page layout *****/
1051 .block-receiver {
1053 .block-receiver {
1052 border:1px dashed #c0c0c0;
1054 border:1px dashed #c0c0c0;
1053 margin-bottom: 20px;
1055 margin-bottom: 20px;
1054 padding: 15px 0 15px 0;
1056 padding: 15px 0 15px 0;
1055 }
1057 }
1056
1058
1057 .mypage-box {
1059 .mypage-box {
1058 margin:0 0 20px 0;
1060 margin:0 0 20px 0;
1059 color:#505050;
1061 color:#505050;
1060 line-height:1.5em;
1062 line-height:1.5em;
1061 }
1063 }
1062
1064
1063 .handle {cursor: move;}
1065 .handle {cursor: move;}
1064
1066
1065 a.close-icon {
1067 a.close-icon {
1066 display:block;
1068 display:block;
1067 margin-top:3px;
1069 margin-top:3px;
1068 overflow:hidden;
1070 overflow:hidden;
1069 width:12px;
1071 width:12px;
1070 height:12px;
1072 height:12px;
1071 background-repeat: no-repeat;
1073 background-repeat: no-repeat;
1072 cursor:pointer;
1074 cursor:pointer;
1073 background-image:url('../images/close.png');
1075 background-image:url('../images/close.png');
1074 }
1076 }
1075 a.close-icon:hover {background-image:url('../images/close_hl.png');}
1077 a.close-icon:hover {background-image:url('../images/close_hl.png');}
1076
1078
1077 /***** Gantt chart *****/
1079 /***** Gantt chart *****/
1078 .gantt_hdr {
1080 .gantt_hdr {
1079 position:absolute;
1081 position:absolute;
1080 top:0;
1082 top:0;
1081 height:16px;
1083 height:16px;
1082 border-top: 1px solid #c0c0c0;
1084 border-top: 1px solid #c0c0c0;
1083 border-bottom: 1px solid #c0c0c0;
1085 border-bottom: 1px solid #c0c0c0;
1084 border-right: 1px solid #c0c0c0;
1086 border-right: 1px solid #c0c0c0;
1085 text-align: center;
1087 text-align: center;
1086 overflow: hidden;
1088 overflow: hidden;
1087 }
1089 }
1088
1090
1089 .gantt_hdr.nwday {background-color:#f1f1f1; color:#999;}
1091 .gantt_hdr.nwday {background-color:#f1f1f1; color:#999;}
1090
1092
1091 .gantt_subjects { font-size: 0.8em; }
1093 .gantt_subjects { font-size: 0.8em; }
1092 .gantt_subjects div { line-height:16px;height:16px;overflow:hidden;white-space:nowrap;text-overflow: ellipsis; }
1094 .gantt_subjects div { line-height:16px;height:16px;overflow:hidden;white-space:nowrap;text-overflow: ellipsis; }
1093
1095
1094 .task {
1096 .task {
1095 position: absolute;
1097 position: absolute;
1096 height:8px;
1098 height:8px;
1097 font-size:0.8em;
1099 font-size:0.8em;
1098 color:#888;
1100 color:#888;
1099 padding:0;
1101 padding:0;
1100 margin:0;
1102 margin:0;
1101 line-height:16px;
1103 line-height:16px;
1102 white-space:nowrap;
1104 white-space:nowrap;
1103 }
1105 }
1104
1106
1105 .task.label {width:100%;}
1107 .task.label {width:100%;}
1106 .task.label.project, .task.label.version { font-weight: bold; }
1108 .task.label.project, .task.label.version { font-weight: bold; }
1107
1109
1108 .task_late { background:#f66 url(../images/task_late.png); border: 1px solid #f66; }
1110 .task_late { background:#f66 url(../images/task_late.png); border: 1px solid #f66; }
1109 .task_done { background:#00c600 url(../images/task_done.png); border: 1px solid #00c600; }
1111 .task_done { background:#00c600 url(../images/task_done.png); border: 1px solid #00c600; }
1110 .task_todo { background:#aaa url(../images/task_todo.png); border: 1px solid #aaa; }
1112 .task_todo { background:#aaa url(../images/task_todo.png); border: 1px solid #aaa; }
1111
1113
1112 .task_todo.parent { background: #888; border: 1px solid #888; height: 3px;}
1114 .task_todo.parent { background: #888; border: 1px solid #888; height: 3px;}
1113 .task_late.parent, .task_done.parent { height: 3px;}
1115 .task_late.parent, .task_done.parent { height: 3px;}
1114 .task.parent.marker.starting { position: absolute; background: url(../images/task_parent_end.png) no-repeat 0 0; width: 8px; height: 16px; margin-left: -4px; left: 0px; top: -1px;}
1116 .task.parent.marker.starting { position: absolute; background: url(../images/task_parent_end.png) no-repeat 0 0; width: 8px; height: 16px; margin-left: -4px; left: 0px; top: -1px;}
1115 .task.parent.marker.ending { position: absolute; background: url(../images/task_parent_end.png) no-repeat 0 0; width: 8px; height: 16px; margin-left: -4px; right: 0px; top: -1px;}
1117 .task.parent.marker.ending { position: absolute; background: url(../images/task_parent_end.png) no-repeat 0 0; width: 8px; height: 16px; margin-left: -4px; right: 0px; top: -1px;}
1116
1118
1117 .version.task_late { background:#f66 url(../images/milestone_late.png); border: 1px solid #f66; height: 2px; margin-top: 3px;}
1119 .version.task_late { background:#f66 url(../images/milestone_late.png); border: 1px solid #f66; height: 2px; margin-top: 3px;}
1118 .version.task_done { background:#00c600 url(../images/milestone_done.png); border: 1px solid #00c600; height: 2px; margin-top: 3px;}
1120 .version.task_done { background:#00c600 url(../images/milestone_done.png); border: 1px solid #00c600; height: 2px; margin-top: 3px;}
1119 .version.task_todo { background:#fff url(../images/milestone_todo.png); border: 1px solid #fff; height: 2px; margin-top: 3px;}
1121 .version.task_todo { background:#fff url(../images/milestone_todo.png); border: 1px solid #fff; height: 2px; margin-top: 3px;}
1120 .version.marker { background-image:url(../images/version_marker.png); background-repeat: no-repeat; border: 0; margin-left: -4px; margin-top: 1px; }
1122 .version.marker { background-image:url(../images/version_marker.png); background-repeat: no-repeat; border: 0; margin-left: -4px; margin-top: 1px; }
1121
1123
1122 .project.task_late { background:#f66 url(../images/milestone_late.png); border: 1px solid #f66; height: 2px; margin-top: 3px;}
1124 .project.task_late { background:#f66 url(../images/milestone_late.png); border: 1px solid #f66; height: 2px; margin-top: 3px;}
1123 .project.task_done { background:#00c600 url(../images/milestone_done.png); border: 1px solid #00c600; height: 2px; margin-top: 3px;}
1125 .project.task_done { background:#00c600 url(../images/milestone_done.png); border: 1px solid #00c600; height: 2px; margin-top: 3px;}
1124 .project.task_todo { background:#fff url(../images/milestone_todo.png); border: 1px solid #fff; height: 2px; margin-top: 3px;}
1126 .project.task_todo { background:#fff url(../images/milestone_todo.png); border: 1px solid #fff; height: 2px; margin-top: 3px;}
1125 .project.marker { background-image:url(../images/project_marker.png); background-repeat: no-repeat; border: 0; margin-left: -4px; margin-top: 1px; }
1127 .project.marker { background-image:url(../images/project_marker.png); background-repeat: no-repeat; border: 0; margin-left: -4px; margin-top: 1px; }
1126
1128
1127 .version-behind-schedule a, .issue-behind-schedule a {color: #f66914;}
1129 .version-behind-schedule a, .issue-behind-schedule a {color: #f66914;}
1128 .version-overdue a, .issue-overdue a, .project-overdue a {color: #f00;}
1130 .version-overdue a, .issue-overdue a, .project-overdue a {color: #f00;}
1129
1131
1130 /***** Icons *****/
1132 /***** Icons *****/
1131 .icon {
1133 .icon {
1132 background-position: 0% 50%;
1134 background-position: 0% 50%;
1133 background-repeat: no-repeat;
1135 background-repeat: no-repeat;
1134 padding-left: 20px;
1136 padding-left: 20px;
1135 padding-top: 2px;
1137 padding-top: 2px;
1136 padding-bottom: 3px;
1138 padding-bottom: 3px;
1137 }
1139 }
1138 .icon-only {
1140 .icon-only {
1139 background-position: 0% 50%;
1141 background-position: 0% 50%;
1140 background-repeat: no-repeat;
1142 background-repeat: no-repeat;
1141 padding-left: 16px;
1143 padding-left: 16px;
1142 display: inline-block;
1144 display: inline-block;
1143 width: 0;
1145 width: 0;
1144 height: 16px;
1146 height: 16px;
1145 overflow: hidden;
1147 overflow: hidden;
1146 padding-top: 0;
1148 padding-top: 0;
1147 padding-bottom: 0;
1149 padding-bottom: 0;
1148 font-size: 8px;
1150 font-size: 8px;
1149 vertical-align: text-bottom;
1151 vertical-align: text-bottom;
1150 }
1152 }
1151 .icon-only::after {
1153 .icon-only::after {
1152 content: "&nbsp;";
1154 content: "&nbsp;";
1153 }
1155 }
1154
1156
1155 .icon-add { background-image: url(../images/add.png); }
1157 .icon-add { background-image: url(../images/add.png); }
1156 .icon-edit { background-image: url(../images/edit.png); }
1158 .icon-edit { background-image: url(../images/edit.png); }
1157 .icon-copy { background-image: url(../images/copy.png); }
1159 .icon-copy { background-image: url(../images/copy.png); }
1158 .icon-duplicate { background-image: url(../images/duplicate.png); }
1160 .icon-duplicate { background-image: url(../images/duplicate.png); }
1159 .icon-del { background-image: url(../images/delete.png); }
1161 .icon-del { background-image: url(../images/delete.png); }
1160 .icon-move { background-image: url(../images/move.png); }
1162 .icon-move { background-image: url(../images/move.png); }
1161 .icon-save { background-image: url(../images/save.png); }
1163 .icon-save { background-image: url(../images/save.png); }
1162 .icon-cancel { background-image: url(../images/cancel.png); }
1164 .icon-cancel { background-image: url(../images/cancel.png); }
1163 .icon-multiple { background-image: url(../images/table_multiple.png); }
1165 .icon-multiple { background-image: url(../images/table_multiple.png); }
1164 .icon-folder { background-image: url(../images/folder.png); }
1166 .icon-folder { background-image: url(../images/folder.png); }
1165 .open .icon-folder { background-image: url(../images/folder_open.png); }
1167 .open .icon-folder { background-image: url(../images/folder_open.png); }
1166 .icon-package { background-image: url(../images/package.png); }
1168 .icon-package { background-image: url(../images/package.png); }
1167 .icon-user { background-image: url(../images/user.png); }
1169 .icon-user { background-image: url(../images/user.png); }
1168 .icon-projects { background-image: url(../images/projects.png); }
1170 .icon-projects { background-image: url(../images/projects.png); }
1169 .icon-help { background-image: url(../images/help.png); }
1171 .icon-help { background-image: url(../images/help.png); }
1170 .icon-attachment { background-image: url(../images/attachment.png); }
1172 .icon-attachment { background-image: url(../images/attachment.png); }
1171 .icon-history { background-image: url(../images/history.png); }
1173 .icon-history { background-image: url(../images/history.png); }
1172 .icon-time { background-image: url(../images/time.png); }
1174 .icon-time { background-image: url(../images/time.png); }
1173 .icon-time-add { background-image: url(../images/time_add.png); }
1175 .icon-time-add { background-image: url(../images/time_add.png); }
1174 .icon-stats { background-image: url(../images/stats.png); }
1176 .icon-stats { background-image: url(../images/stats.png); }
1175 .icon-warning { background-image: url(../images/warning.png); }
1177 .icon-warning { background-image: url(../images/warning.png); }
1176 .icon-error { background-image: url(../images/exclamation.png); }
1178 .icon-error { background-image: url(../images/exclamation.png); }
1177 .icon-fav { background-image: url(../images/fav.png); }
1179 .icon-fav { background-image: url(../images/fav.png); }
1178 .icon-fav-off { background-image: url(../images/fav_off.png); }
1180 .icon-fav-off { background-image: url(../images/fav_off.png); }
1179 .icon-reload { background-image: url(../images/reload.png); }
1181 .icon-reload { background-image: url(../images/reload.png); }
1180 .icon-lock { background-image: url(../images/locked.png); }
1182 .icon-lock { background-image: url(../images/locked.png); }
1181 .icon-unlock { background-image: url(../images/unlock.png); }
1183 .icon-unlock { background-image: url(../images/unlock.png); }
1182 .icon-checked { background-image: url(../images/toggle_check.png); }
1184 .icon-checked { background-image: url(../images/toggle_check.png); }
1183 .icon-details { background-image: url(../images/zoom_in.png); }
1185 .icon-details { background-image: url(../images/zoom_in.png); }
1184 .icon-report { background-image: url(../images/report.png); }
1186 .icon-report { background-image: url(../images/report.png); }
1185 .icon-comment { background-image: url(../images/comment.png); }
1187 .icon-comment { background-image: url(../images/comment.png); }
1186 .icon-summary { background-image: url(../images/lightning.png); }
1188 .icon-summary { background-image: url(../images/lightning.png); }
1187 .icon-server-authentication { background-image: url(../images/server_key.png); }
1189 .icon-server-authentication { background-image: url(../images/server_key.png); }
1188 .icon-issue { background-image: url(../images/ticket.png); }
1190 .icon-issue { background-image: url(../images/ticket.png); }
1189 .icon-zoom-in { background-image: url(../images/zoom_in.png); }
1191 .icon-zoom-in { background-image: url(../images/zoom_in.png); }
1190 .icon-zoom-out { background-image: url(../images/zoom_out.png); }
1192 .icon-zoom-out { background-image: url(../images/zoom_out.png); }
1191 .icon-magnifier { background-image: url(../images/magnifier.png); }
1193 .icon-magnifier { background-image: url(../images/magnifier.png); }
1192 .icon-passwd { background-image: url(../images/textfield_key.png); }
1194 .icon-passwd { background-image: url(../images/textfield_key.png); }
1193 .icon-test { background-image: url(../images/bullet_go.png); }
1195 .icon-test { background-image: url(../images/bullet_go.png); }
1194 .icon-email { background-image: url(../images/email.png); }
1196 .icon-email { background-image: url(../images/email.png); }
1195 .icon-email-disabled { background-image: url(../images/email_disabled.png); }
1197 .icon-email-disabled { background-image: url(../images/email_disabled.png); }
1196 .icon-email-add { background-image: url(../images/email_add.png); }
1198 .icon-email-add { background-image: url(../images/email_add.png); }
1197 .icon-move-up { background-image: url(../images/1uparrow.png); }
1199 .icon-move-up { background-image: url(../images/1uparrow.png); }
1198 .icon-move-top { background-image: url(../images/2uparrow.png); }
1200 .icon-move-top { background-image: url(../images/2uparrow.png); }
1199 .icon-move-down { background-image: url(../images/1downarrow.png); }
1201 .icon-move-down { background-image: url(../images/1downarrow.png); }
1200 .icon-move-bottom { background-image: url(../images/2downarrow.png); }
1202 .icon-move-bottom { background-image: url(../images/2downarrow.png); }
1201 .icon-ok { background-image: url(../images/true.png); }
1203 .icon-ok { background-image: url(../images/true.png); }
1202 .icon-not-ok { background-image: url(../images/false.png); }
1204 .icon-not-ok { background-image: url(../images/false.png); }
1203 .icon-link-break { background-image: url(../images/link_break.png); }
1205 .icon-link-break { background-image: url(../images/link_break.png); }
1204 .icon-list { background-image: url(../images/text_list_bullets.png); }
1206 .icon-list { background-image: url(../images/text_list_bullets.png); }
1205
1207
1206 .icon-file { background-image: url(../images/files/default.png); }
1208 .icon-file { background-image: url(../images/files/default.png); }
1207 .icon-file.text-plain { background-image: url(../images/files/text.png); }
1209 .icon-file.text-plain { background-image: url(../images/files/text.png); }
1208 .icon-file.text-x-c { background-image: url(../images/files/c.png); }
1210 .icon-file.text-x-c { background-image: url(../images/files/c.png); }
1209 .icon-file.text-x-csharp { background-image: url(../images/files/csharp.png); }
1211 .icon-file.text-x-csharp { background-image: url(../images/files/csharp.png); }
1210 .icon-file.text-x-java { background-image: url(../images/files/java.png); }
1212 .icon-file.text-x-java { background-image: url(../images/files/java.png); }
1211 .icon-file.text-x-javascript { background-image: url(../images/files/js.png); }
1213 .icon-file.text-x-javascript { background-image: url(../images/files/js.png); }
1212 .icon-file.text-x-php { background-image: url(../images/files/php.png); }
1214 .icon-file.text-x-php { background-image: url(../images/files/php.png); }
1213 .icon-file.text-x-ruby { background-image: url(../images/files/ruby.png); }
1215 .icon-file.text-x-ruby { background-image: url(../images/files/ruby.png); }
1214 .icon-file.text-xml { background-image: url(../images/files/xml.png); }
1216 .icon-file.text-xml { background-image: url(../images/files/xml.png); }
1215 .icon-file.text-css { background-image: url(../images/files/css.png); }
1217 .icon-file.text-css { background-image: url(../images/files/css.png); }
1216 .icon-file.text-html { background-image: url(../images/files/html.png); }
1218 .icon-file.text-html { background-image: url(../images/files/html.png); }
1217 .icon-file.image-gif { background-image: url(../images/files/image.png); }
1219 .icon-file.image-gif { background-image: url(../images/files/image.png); }
1218 .icon-file.image-jpeg { background-image: url(../images/files/image.png); }
1220 .icon-file.image-jpeg { background-image: url(../images/files/image.png); }
1219 .icon-file.image-png { background-image: url(../images/files/image.png); }
1221 .icon-file.image-png { background-image: url(../images/files/image.png); }
1220 .icon-file.image-tiff { background-image: url(../images/files/image.png); }
1222 .icon-file.image-tiff { background-image: url(../images/files/image.png); }
1221 .icon-file.application-pdf { background-image: url(../images/files/pdf.png); }
1223 .icon-file.application-pdf { background-image: url(../images/files/pdf.png); }
1222 .icon-file.application-zip { background-image: url(../images/files/zip.png); }
1224 .icon-file.application-zip { background-image: url(../images/files/zip.png); }
1223 .icon-file.application-x-gzip { background-image: url(../images/files/zip.png); }
1225 .icon-file.application-x-gzip { background-image: url(../images/files/zip.png); }
1224
1226
1225 .sort-handle { width:16px; height:16px; background:url(../images/reorder.png) no-repeat 0 50%; cursor:move; }
1227 .sort-handle { width:16px; height:16px; background:url(../images/reorder.png) no-repeat 0 50%; cursor:move; }
1226 .sort-handle.ajax-loading { background-image: url(../images/loading.gif); }
1228 .sort-handle.ajax-loading { background-image: url(../images/loading.gif); }
1227 tr.ui-sortable-helper { border:1px solid #e4e4e4; }
1229 tr.ui-sortable-helper { border:1px solid #e4e4e4; }
1228
1230
1229 .contextual>.icon:not(:first-child), .buttons>.icon:not(:first-child) { margin-left: 5px; }
1231 .contextual>.icon:not(:first-child), .buttons>.icon:not(:first-child) { margin-left: 5px; }
1230
1232
1231 img.gravatar {
1233 img.gravatar {
1232 vertical-align: middle;
1234 vertical-align: middle;
1233 border-radius: 20%;
1235 border-radius: 20%;
1234 }
1236 }
1235
1237
1236 div.issue img.gravatar {
1238 div.issue img.gravatar {
1237 float: left;
1239 float: left;
1238 margin: 0 6px 0 0;
1240 margin: 0 6px 0 0;
1239 }
1241 }
1240
1242
1241 h2 img.gravatar {margin: -2px 4px -4px 0;}
1243 h2 img.gravatar {margin: -2px 4px -4px 0;}
1242 h3 img.gravatar {margin: -4px 4px -4px 0;}
1244 h3 img.gravatar {margin: -4px 4px -4px 0;}
1243 h4 img.gravatar {margin: -2px 4px -4px 0;}
1245 h4 img.gravatar {margin: -2px 4px -4px 0;}
1244 td.username img.gravatar {margin: 0 0.5em 0 0; vertical-align: top;}
1246 td.username img.gravatar {margin: 0 0.5em 0 0; vertical-align: top;}
1245 #activity dt img.gravatar {float: left; margin: 0 1em 1em 0;}
1247 #activity dt img.gravatar {float: left; margin: 0 1em 1em 0;}
1246 /* Used on 12px Gravatar img tags without the icon background */
1248 /* Used on 12px Gravatar img tags without the icon background */
1247 .icon-gravatar {float: left; margin-right: 4px;}
1249 .icon-gravatar {float: left; margin-right: 4px;}
1248
1250
1249 #activity dt, .journal {clear: left;}
1251 #activity dt, .journal {clear: left;}
1250
1252
1251 .journal-link {float: right;}
1253 .journal-link {float: right;}
1252
1254
1253 h2 img { vertical-align:middle; }
1255 h2 img { vertical-align:middle; }
1254
1256
1255 .hascontextmenu { cursor: context-menu; }
1257 .hascontextmenu { cursor: context-menu; }
1256
1258
1257 .sample-data {border:1px solid #ccc; border-collapse:collapse; background-color:#fff; margin:0.5em;}
1259 .sample-data {border:1px solid #ccc; border-collapse:collapse; background-color:#fff; margin:0.5em;}
1258 .sample-data td {border:1px solid #ccc; padding: 2px 4px; font-family: Consolas, Menlo, "Liberation Mono", Courier, monospace;}
1260 .sample-data td {border:1px solid #ccc; padding: 2px 4px; font-family: Consolas, Menlo, "Liberation Mono", Courier, monospace;}
1259 .sample-data tr:first-child td {font-weight:bold; text-align:center;}
1261 .sample-data tr:first-child td {font-weight:bold; text-align:center;}
1260
1262
1261 .ui-progressbar {position: relative;}
1263 .ui-progressbar {position: relative;}
1262 #progress-label {
1264 #progress-label {
1263 position: absolute; left: 50%; top: 4px;
1265 position: absolute; left: 50%; top: 4px;
1264 font-weight: bold;
1266 font-weight: bold;
1265 color: #555; text-shadow: 1px 1px 0 #fff;
1267 color: #555; text-shadow: 1px 1px 0 #fff;
1266 }
1268 }
1267
1269
1268 /* Custom JQuery styles */
1270 /* Custom JQuery styles */
1269 .ui-datepicker-title select {width:70px !important; margin-top:-2px !important; margin-right:4px !important;}
1271 .ui-datepicker-title select {width:70px !important; margin-top:-2px !important; margin-right:4px !important;}
1270
1272
1271
1273
1272 /************* CodeRay styles *************/
1274 /************* CodeRay styles *************/
1273 .syntaxhl div {display: inline;}
1275 .syntaxhl div {display: inline;}
1274 .syntaxhl .code pre { overflow: auto }
1276 .syntaxhl .code pre { overflow: auto }
1275
1277
1276 .syntaxhl .annotation { color:#007 }
1278 .syntaxhl .annotation { color:#007 }
1277 .syntaxhl .attribute-name { color:#b48 }
1279 .syntaxhl .attribute-name { color:#b48 }
1278 .syntaxhl .attribute-value { color:#700 }
1280 .syntaxhl .attribute-value { color:#700 }
1279 .syntaxhl .binary { color:#549 }
1281 .syntaxhl .binary { color:#549 }
1280 .syntaxhl .binary .char { color:#325 }
1282 .syntaxhl .binary .char { color:#325 }
1281 .syntaxhl .binary .delimiter { color:#325 }
1283 .syntaxhl .binary .delimiter { color:#325 }
1282 .syntaxhl .char { color:#D20 }
1284 .syntaxhl .char { color:#D20 }
1283 .syntaxhl .char .content { color:#D20 }
1285 .syntaxhl .char .content { color:#D20 }
1284 .syntaxhl .char .delimiter { color:#710 }
1286 .syntaxhl .char .delimiter { color:#710 }
1285 .syntaxhl .class { color:#B06; font-weight:bold }
1287 .syntaxhl .class { color:#B06; font-weight:bold }
1286 .syntaxhl .class-variable { color:#369 }
1288 .syntaxhl .class-variable { color:#369 }
1287 .syntaxhl .color { color:#0A0 }
1289 .syntaxhl .color { color:#0A0 }
1288 .syntaxhl .comment { color:#777 }
1290 .syntaxhl .comment { color:#777 }
1289 .syntaxhl .comment .char { color:#444 }
1291 .syntaxhl .comment .char { color:#444 }
1290 .syntaxhl .comment .delimiter { color:#444 }
1292 .syntaxhl .comment .delimiter { color:#444 }
1291 .syntaxhl .constant { color:#036; font-weight:bold }
1293 .syntaxhl .constant { color:#036; font-weight:bold }
1292 .syntaxhl .decorator { color:#B0B }
1294 .syntaxhl .decorator { color:#B0B }
1293 .syntaxhl .definition { color:#099; font-weight:bold }
1295 .syntaxhl .definition { color:#099; font-weight:bold }
1294 .syntaxhl .delimiter { color:black }
1296 .syntaxhl .delimiter { color:black }
1295 .syntaxhl .directive { color:#088; font-weight:bold }
1297 .syntaxhl .directive { color:#088; font-weight:bold }
1296 .syntaxhl .docstring { color:#D42; }
1298 .syntaxhl .docstring { color:#D42; }
1297 .syntaxhl .doctype { color:#34b }
1299 .syntaxhl .doctype { color:#34b }
1298 .syntaxhl .done { text-decoration: line-through; color: gray }
1300 .syntaxhl .done { text-decoration: line-through; color: gray }
1299 .syntaxhl .entity { color:#800; font-weight:bold }
1301 .syntaxhl .entity { color:#800; font-weight:bold }
1300 .syntaxhl .error { color:#F00; background-color:#FAA }
1302 .syntaxhl .error { color:#F00; background-color:#FAA }
1301 .syntaxhl .escape { color:#666 }
1303 .syntaxhl .escape { color:#666 }
1302 .syntaxhl .exception { color:#C00; font-weight:bold }
1304 .syntaxhl .exception { color:#C00; font-weight:bold }
1303 .syntaxhl .float { color:#60E }
1305 .syntaxhl .float { color:#60E }
1304 .syntaxhl .function { color:#06B; font-weight:bold }
1306 .syntaxhl .function { color:#06B; font-weight:bold }
1305 .syntaxhl .function .delimiter { color:#059 }
1307 .syntaxhl .function .delimiter { color:#059 }
1306 .syntaxhl .function .content { color:#037 }
1308 .syntaxhl .function .content { color:#037 }
1307 .syntaxhl .global-variable { color:#d70 }
1309 .syntaxhl .global-variable { color:#d70 }
1308 .syntaxhl .hex { color:#02b }
1310 .syntaxhl .hex { color:#02b }
1309 .syntaxhl .id { color:#33D; font-weight:bold }
1311 .syntaxhl .id { color:#33D; font-weight:bold }
1310 .syntaxhl .include { color:#B44; font-weight:bold }
1312 .syntaxhl .include { color:#B44; font-weight:bold }
1311 .syntaxhl .inline { background-color: hsla(0,0%,0%,0.07); color: black }
1313 .syntaxhl .inline { background-color: hsla(0,0%,0%,0.07); color: black }
1312 .syntaxhl .inline-delimiter { font-weight: bold; color: #666 }
1314 .syntaxhl .inline-delimiter { font-weight: bold; color: #666 }
1313 .syntaxhl .instance-variable { color:#33B }
1315 .syntaxhl .instance-variable { color:#33B }
1314 .syntaxhl .integer { color:#00D }
1316 .syntaxhl .integer { color:#00D }
1315 .syntaxhl .imaginary { color:#f00 }
1317 .syntaxhl .imaginary { color:#f00 }
1316 .syntaxhl .important { color:#D00 }
1318 .syntaxhl .important { color:#D00 }
1317 .syntaxhl .key { color: #606 }
1319 .syntaxhl .key { color: #606 }
1318 .syntaxhl .key .char { color: #60f }
1320 .syntaxhl .key .char { color: #60f }
1319 .syntaxhl .key .delimiter { color: #404 }
1321 .syntaxhl .key .delimiter { color: #404 }
1320 .syntaxhl .keyword { color:#080; font-weight:bold }
1322 .syntaxhl .keyword { color:#080; font-weight:bold }
1321 .syntaxhl .label { color:#970; font-weight:bold }
1323 .syntaxhl .label { color:#970; font-weight:bold }
1322 .syntaxhl .local-variable { color:#950 }
1324 .syntaxhl .local-variable { color:#950 }
1323 .syntaxhl .map .content { color:#808 }
1325 .syntaxhl .map .content { color:#808 }
1324 .syntaxhl .map .delimiter { color:#40A}
1326 .syntaxhl .map .delimiter { color:#40A}
1325 .syntaxhl .map { background-color:hsla(200,100%,50%,0.06); }
1327 .syntaxhl .map { background-color:hsla(200,100%,50%,0.06); }
1326 .syntaxhl .namespace { color:#707; font-weight:bold }
1328 .syntaxhl .namespace { color:#707; font-weight:bold }
1327 .syntaxhl .octal { color:#40E }
1329 .syntaxhl .octal { color:#40E }
1328 .syntaxhl .operator { }
1330 .syntaxhl .operator { }
1329 .syntaxhl .predefined { color:#369; font-weight:bold }
1331 .syntaxhl .predefined { color:#369; font-weight:bold }
1330 .syntaxhl .predefined-constant { color:#069 }
1332 .syntaxhl .predefined-constant { color:#069 }
1331 .syntaxhl .predefined-type { color:#0a8; font-weight:bold }
1333 .syntaxhl .predefined-type { color:#0a8; font-weight:bold }
1332 .syntaxhl .preprocessor { color:#579 }
1334 .syntaxhl .preprocessor { color:#579 }
1333 .syntaxhl .pseudo-class { color:#00C; font-weight:bold }
1335 .syntaxhl .pseudo-class { color:#00C; font-weight:bold }
1334 .syntaxhl .regexp { background-color:hsla(300,100%,50%,0.06); }
1336 .syntaxhl .regexp { background-color:hsla(300,100%,50%,0.06); }
1335 .syntaxhl .regexp .content { color:#808 }
1337 .syntaxhl .regexp .content { color:#808 }
1336 .syntaxhl .regexp .delimiter { color:#404 }
1338 .syntaxhl .regexp .delimiter { color:#404 }
1337 .syntaxhl .regexp .modifier { color:#C2C }
1339 .syntaxhl .regexp .modifier { color:#C2C }
1338 .syntaxhl .reserved { color:#080; font-weight:bold }
1340 .syntaxhl .reserved { color:#080; font-weight:bold }
1339 .syntaxhl .shell { background-color:hsla(120,100%,50%,0.06); }
1341 .syntaxhl .shell { background-color:hsla(120,100%,50%,0.06); }
1340 .syntaxhl .shell .content { color:#2B2 }
1342 .syntaxhl .shell .content { color:#2B2 }
1341 .syntaxhl .shell .delimiter { color:#161 }
1343 .syntaxhl .shell .delimiter { color:#161 }
1342 .syntaxhl .string { background-color:hsla(0,100%,50%,0.05); }
1344 .syntaxhl .string { background-color:hsla(0,100%,50%,0.05); }
1343 .syntaxhl .string .char { color: #b0b }
1345 .syntaxhl .string .char { color: #b0b }
1344 .syntaxhl .string .content { color: #D20 }
1346 .syntaxhl .string .content { color: #D20 }
1345 .syntaxhl .string .delimiter { color: #710 }
1347 .syntaxhl .string .delimiter { color: #710 }
1346 .syntaxhl .string .modifier { color: #E40 }
1348 .syntaxhl .string .modifier { color: #E40 }
1347 .syntaxhl .symbol { color:#A60 }
1349 .syntaxhl .symbol { color:#A60 }
1348 .syntaxhl .symbol .content { color:#A60 }
1350 .syntaxhl .symbol .content { color:#A60 }
1349 .syntaxhl .symbol .delimiter { color:#740 }
1351 .syntaxhl .symbol .delimiter { color:#740 }
1350 .syntaxhl .tag { color:#070; font-weight:bold }
1352 .syntaxhl .tag { color:#070; font-weight:bold }
1351 .syntaxhl .type { color:#339; font-weight:bold }
1353 .syntaxhl .type { color:#339; font-weight:bold }
1352 .syntaxhl .value { color: #088 }
1354 .syntaxhl .value { color: #088 }
1353 .syntaxhl .variable { color:#037 }
1355 .syntaxhl .variable { color:#037 }
1354
1356
1355 .syntaxhl .insert { background: hsla(120,100%,50%,0.12) }
1357 .syntaxhl .insert { background: hsla(120,100%,50%,0.12) }
1356 .syntaxhl .delete { background: hsla(0,100%,50%,0.12) }
1358 .syntaxhl .delete { background: hsla(0,100%,50%,0.12) }
1357 .syntaxhl .change { color: #bbf; background: #007 }
1359 .syntaxhl .change { color: #bbf; background: #007 }
1358 .syntaxhl .head { color: #f8f; background: #505 }
1360 .syntaxhl .head { color: #f8f; background: #505 }
1359 .syntaxhl .head .filename { color: white; }
1361 .syntaxhl .head .filename { color: white; }
1360
1362
1361 .syntaxhl .delete .eyecatcher { background-color: hsla(0,100%,50%,0.2); border: 1px solid hsla(0,100%,45%,0.5); margin: -1px; border-bottom: none; border-top-left-radius: 5px; border-top-right-radius: 5px; }
1363 .syntaxhl .delete .eyecatcher { background-color: hsla(0,100%,50%,0.2); border: 1px solid hsla(0,100%,45%,0.5); margin: -1px; border-bottom: none; border-top-left-radius: 5px; border-top-right-radius: 5px; }
1362 .syntaxhl .insert .eyecatcher { background-color: hsla(120,100%,50%,0.2); border: 1px solid hsla(120,100%,25%,0.5); margin: -1px; border-top: none; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; }
1364 .syntaxhl .insert .eyecatcher { background-color: hsla(120,100%,50%,0.2); border: 1px solid hsla(120,100%,25%,0.5); margin: -1px; border-top: none; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; }
1363
1365
1364 .syntaxhl .insert .insert { color: #0c0; background:transparent; font-weight:bold }
1366 .syntaxhl .insert .insert { color: #0c0; background:transparent; font-weight:bold }
1365 .syntaxhl .delete .delete { color: #c00; background:transparent; font-weight:bold }
1367 .syntaxhl .delete .delete { color: #c00; background:transparent; font-weight:bold }
1366 .syntaxhl .change .change { color: #88f }
1368 .syntaxhl .change .change { color: #88f }
1367 .syntaxhl .head .head { color: #f4f }
1369 .syntaxhl .head .head { color: #f4f }
1368
1370
1369 /***** Media print specific styles *****/
1371 /***** Media print specific styles *****/
1370 @media print {
1372 @media print {
1371 #top-menu, #header, #main-menu, #sidebar, #footer, .contextual, .other-formats { display:none; }
1373 #top-menu, #header, #main-menu, #sidebar, #footer, .contextual, .other-formats { display:none; }
1372 #main { background: #fff; }
1374 #main { background: #fff; }
1373 #content { width: 99%; margin: 0; padding: 0; border: 0; background: #fff; overflow: visible !important;}
1375 #content { width: 99%; margin: 0; padding: 0; border: 0; background: #fff; overflow: visible !important;}
1374 #wiki_add_attachment { display:none; }
1376 #wiki_add_attachment { display:none; }
1375 .hide-when-print, .pagination ul.pages, .pagination .per-page { display: none !important; }
1377 .hide-when-print, .pagination ul.pages, .pagination .per-page { display: none !important; }
1376 .autoscroll {overflow-x: visible;}
1378 .autoscroll {overflow-x: visible;}
1377 table.list {margin-top:0.5em;}
1379 table.list {margin-top:0.5em;}
1378 table.list th, table.list td {border: 1px solid #aaa;}
1380 table.list th, table.list td {border: 1px solid #aaa;}
1379 }
1381 }
1380
1382
1381 /* Accessibility specific styles */
1383 /* Accessibility specific styles */
1382 .hidden-for-sighted {
1384 .hidden-for-sighted {
1383 position:absolute;
1385 position:absolute;
1384 left:-10000px;
1386 left:-10000px;
1385 top:auto;
1387 top:auto;
1386 width:1px;
1388 width:1px;
1387 height:1px;
1389 height:1px;
1388 overflow:hidden;
1390 overflow:hidden;
1389 }
1391 }
@@ -1,633 +1,635
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.expand_path('../../test_helper', __FILE__)
18 require File.expand_path('../../test_helper', __FILE__)
19
19
20 class UsersControllerTest < Redmine::ControllerTest
20 class UsersControllerTest < Redmine::ControllerTest
21 include Redmine::I18n
21 include Redmine::I18n
22
22
23 fixtures :users, :email_addresses, :projects, :members, :member_roles, :roles,
23 fixtures :users, :email_addresses, :projects, :members, :member_roles, :roles,
24 :custom_fields, :custom_values, :groups_users,
24 :custom_fields, :custom_values, :groups_users,
25 :auth_sources,
25 :auth_sources,
26 :enabled_modules,
26 :enabled_modules,
27 :issues, :issue_statuses,
27 :issues, :issue_statuses,
28 :trackers
28 :trackers
29
29
30 def setup
30 def setup
31 User.current = nil
31 User.current = nil
32 @request.session[:user_id] = 1 # admin
32 @request.session[:user_id] = 1 # admin
33 end
33 end
34
34
35 def test_index
35 def test_index
36 get :index
36 get :index
37 assert_response :success
37 assert_response :success
38 assert_select 'table.users'
38 assert_select 'table.users'
39 assert_select 'tr.user.active'
39 assert_select 'tr.user.active'
40 assert_select 'tr.user.locked', 0
40 assert_select 'tr.user.locked', 0
41 end
41 end
42
42
43 def test_index_with_status_filter
43 def test_index_with_status_filter
44 get :index, :params => {:status => 3}
44 get :index, :params => {:status => 3}
45 assert_response :success
45 assert_response :success
46 assert_select 'tr.user.active', 0
46 assert_select 'tr.user.active', 0
47 assert_select 'tr.user.locked'
47 assert_select 'tr.user.locked'
48 end
48 end
49
49
50 def test_index_with_name_filter
50 def test_index_with_name_filter
51 get :index, :params => {:name => 'john'}
51 get :index, :params => {:name => 'john'}
52 assert_response :success
52 assert_response :success
53 assert_select 'tr.user td.username', :text => 'jsmith'
53 assert_select 'tr.user td.username', :text => 'jsmith'
54 assert_select 'tr.user', 1
54 assert_select 'tr.user', 1
55 end
55 end
56
56
57 def test_index_with_group_filter
57 def test_index_with_group_filter
58 get :index, :params => {:group_id => '10'}
58 get :index, :params => {:group_id => '10'}
59 assert_response :success
59 assert_response :success
60
60
61 assert_select 'tr.user', Group.find(10).users.count
61 assert_select 'tr.user', Group.find(10).users.count
62 assert_select 'select[name=group_id]' do
62 assert_select 'select[name=group_id]' do
63 assert_select 'option[value="10"][selected=selected]'
63 assert_select 'option[value="10"][selected=selected]'
64 end
64 end
65 end
65 end
66
66
67 def test_show
67 def test_show
68 @request.session[:user_id] = nil
68 @request.session[:user_id] = nil
69 get :show, :params => {:id => 2}
69 get :show, :params => {:id => 2}
70 assert_response :success
70 assert_response :success
71 assert_select 'h2', :text => /John Smith/
71 assert_select 'h2', :text => /John Smith/
72 end
72 end
73
73
74 def test_show_should_display_visible_custom_fields
74 def test_show_should_display_visible_custom_fields
75 @request.session[:user_id] = nil
75 @request.session[:user_id] = nil
76 UserCustomField.find_by_name('Phone number').update_attribute :visible, true
76 UserCustomField.find_by_name('Phone number').update_attribute :visible, true
77 get :show, :params => {:id => 2}
77 get :show, :params => {:id => 2}
78 assert_response :success
78 assert_response :success
79
79
80 assert_select 'li', :text => /Phone number/
80 assert_select 'li', :text => /Phone number/
81 end
81 end
82
82
83 def test_show_should_not_display_hidden_custom_fields
83 def test_show_should_not_display_hidden_custom_fields
84 @request.session[:user_id] = nil
84 @request.session[:user_id] = nil
85 UserCustomField.find_by_name('Phone number').update_attribute :visible, false
85 UserCustomField.find_by_name('Phone number').update_attribute :visible, false
86 get :show, :params => {:id => 2}
86 get :show, :params => {:id => 2}
87 assert_response :success
87 assert_response :success
88
88
89 assert_select 'li', :text => /Phone number/, :count => 0
89 assert_select 'li', :text => /Phone number/, :count => 0
90 end
90 end
91
91
92 def test_show_should_not_fail_when_custom_values_are_nil
92 def test_show_should_not_fail_when_custom_values_are_nil
93 user = User.find(2)
93 user = User.find(2)
94
94
95 # Create a custom field to illustrate the issue
95 # Create a custom field to illustrate the issue
96 custom_field = CustomField.create!(:name => 'Testing', :field_format => 'text')
96 custom_field = CustomField.create!(:name => 'Testing', :field_format => 'text')
97 custom_value = user.custom_values.build(:custom_field => custom_field).save!
97 custom_value = user.custom_values.build(:custom_field => custom_field).save!
98
98
99 get :show, :params => {:id => 2}
99 get :show, :params => {:id => 2}
100 assert_response :success
100 assert_response :success
101 end
101 end
102
102
103 def test_show_inactive
103 def test_show_inactive
104 @request.session[:user_id] = nil
104 @request.session[:user_id] = nil
105 get :show, :params => {:id => 5}
105 get :show, :params => {:id => 5}
106 assert_response 404
106 assert_response 404
107 end
107 end
108
108
109 def test_show_inactive_by_admin
109 def test_show_inactive_by_admin
110 @request.session[:user_id] = 1
110 @request.session[:user_id] = 1
111 get :show, :params => {:id => 5}
111 get :show, :params => {:id => 5}
112 assert_response 200
112 assert_response 200
113 assert_select 'h2', :text => /Dave2 Lopper2/
113 assert_select 'h2', :text => /Dave2 Lopper2/
114 end
114 end
115
115
116 def test_show_user_who_is_not_visible_should_return_404
116 def test_show_user_who_is_not_visible_should_return_404
117 Role.anonymous.update! :users_visibility => 'members_of_visible_projects'
117 Role.anonymous.update! :users_visibility => 'members_of_visible_projects'
118 user = User.generate!
118 user = User.generate!
119
119
120 @request.session[:user_id] = nil
120 @request.session[:user_id] = nil
121 get :show, :params => {:id => user.id}
121 get :show, :params => {:id => user.id}
122 assert_response 404
122 assert_response 404
123 end
123 end
124
124
125 def test_show_displays_memberships_based_on_project_visibility
125 def test_show_displays_memberships_based_on_project_visibility
126 @request.session[:user_id] = 1
126 @request.session[:user_id] = 1
127 get :show, :params => {:id => 2}
127 get :show, :params => {:id => 2}
128 assert_response :success
128 assert_response :success
129
129
130 # membership of private project admin can see
130 # membership of private project admin can see
131 assert_select 'li a', :text => "OnlineStore"
131 assert_select 'li a', :text => "OnlineStore"
132 end
132 end
133
133
134 def test_show_current_should_require_authentication
134 def test_show_current_should_require_authentication
135 @request.session[:user_id] = nil
135 @request.session[:user_id] = nil
136 get :show, :params => {:id => 'current'}
136 get :show, :params => {:id => 'current'}
137 assert_response 302
137 assert_response 302
138 end
138 end
139
139
140 def test_show_current
140 def test_show_current
141 @request.session[:user_id] = 2
141 @request.session[:user_id] = 2
142 get :show, :params => {:id => 'current'}
142 get :show, :params => {:id => 'current'}
143 assert_response :success
143 assert_response :success
144 assert_select 'h2', :text => /John Smith/
144 assert_select 'h2', :text => /John Smith/
145 end
145 end
146
146
147 def test_new
147 def test_new
148 get :new
148 get :new
149 assert_response :success
149 assert_response :success
150 assert_select 'input[name=?]', 'user[login]'
150 assert_select 'input[name=?]', 'user[login]'
151 end
151 end
152
152
153 def test_create
153 def test_create
154 Setting.bcc_recipients = '1'
154 Setting.bcc_recipients = '1'
155
155
156 assert_difference 'User.count' do
156 assert_difference 'User.count' do
157 assert_difference 'ActionMailer::Base.deliveries.size' do
157 assert_difference 'ActionMailer::Base.deliveries.size' do
158 post :create, :params => {
158 post :create, :params => {
159 :user => {
159 :user => {
160 :firstname => 'John',
160 :firstname => 'John',
161 :lastname => 'Doe',
161 :lastname => 'Doe',
162 :login => 'jdoe',
162 :login => 'jdoe',
163 :password => 'secret123',
163 :password => 'secret123',
164 :password_confirmation => 'secret123',
164 :password_confirmation => 'secret123',
165 :mail => 'jdoe@gmail.com',
165 :mail => 'jdoe@gmail.com',
166 :mail_notification => 'none'
166 :mail_notification => 'none'
167 },
167 },
168 :send_information => '1'
168 :send_information => '1'
169 }
169 }
170 end
170 end
171 end
171 end
172
172
173 user = User.order('id DESC').first
173 user = User.order('id DESC').first
174 assert_redirected_to :controller => 'users', :action => 'edit', :id => user.id
174 assert_redirected_to :controller => 'users', :action => 'edit', :id => user.id
175
175
176 assert_equal 'John', user.firstname
176 assert_equal 'John', user.firstname
177 assert_equal 'Doe', user.lastname
177 assert_equal 'Doe', user.lastname
178 assert_equal 'jdoe', user.login
178 assert_equal 'jdoe', user.login
179 assert_equal 'jdoe@gmail.com', user.mail
179 assert_equal 'jdoe@gmail.com', user.mail
180 assert_equal 'none', user.mail_notification
180 assert_equal 'none', user.mail_notification
181 assert user.check_password?('secret123')
181 assert user.check_password?('secret123')
182
182
183 mail = ActionMailer::Base.deliveries.last
183 mail = ActionMailer::Base.deliveries.last
184 assert_not_nil mail
184 assert_not_nil mail
185 assert_equal [user.mail], mail.bcc
185 assert_equal [user.mail], mail.bcc
186 assert_mail_body_match 'secret', mail
186 assert_mail_body_match 'secret', mail
187 end
187 end
188
188
189 def test_create_with_preferences
189 def test_create_with_preferences
190 assert_difference 'User.count' do
190 assert_difference 'User.count' do
191 post :create, :params => {
191 post :create, :params => {
192 :user => {
192 :user => {
193 :firstname => 'John',
193 :firstname => 'John',
194 :lastname => 'Doe',
194 :lastname => 'Doe',
195 :login => 'jdoe',
195 :login => 'jdoe',
196 :password => 'secret123',
196 :password => 'secret123',
197 :password_confirmation => 'secret123',
197 :password_confirmation => 'secret123',
198 :mail => 'jdoe@gmail.com',
198 :mail => 'jdoe@gmail.com',
199 :mail_notification => 'none'
199 :mail_notification => 'none'
200 },
200 },
201 :pref => {
201 :pref => {
202 'hide_mail' => '1',
202 'hide_mail' => '1',
203 'time_zone' => 'Paris',
203 'time_zone' => 'Paris',
204 'comments_sorting' => 'desc',
204 'comments_sorting' => 'desc',
205 'warn_on_leaving_unsaved' => '0'
205 'warn_on_leaving_unsaved' => '0',
206 'textarea_font' => 'proportional'
206 }
207 }
207 }
208 }
208 end
209 end
209 user = User.order('id DESC').first
210 user = User.order('id DESC').first
210 assert_equal 'jdoe', user.login
211 assert_equal 'jdoe', user.login
211 assert_equal true, user.pref.hide_mail
212 assert_equal true, user.pref.hide_mail
212 assert_equal 'Paris', user.pref.time_zone
213 assert_equal 'Paris', user.pref.time_zone
213 assert_equal 'desc', user.pref[:comments_sorting]
214 assert_equal 'desc', user.pref[:comments_sorting]
214 assert_equal '0', user.pref[:warn_on_leaving_unsaved]
215 assert_equal '0', user.pref[:warn_on_leaving_unsaved]
216 assert_equal 'proportional', user.pref[:textarea_font]
215 end
217 end
216
218
217 def test_create_with_generate_password_should_email_the_password
219 def test_create_with_generate_password_should_email_the_password
218 assert_difference 'User.count' do
220 assert_difference 'User.count' do
219 post :create, :params => {
221 post :create, :params => {
220 :user => {
222 :user => {
221 :login => 'randompass',
223 :login => 'randompass',
222 :firstname => 'Random',
224 :firstname => 'Random',
223 :lastname => 'Pass',
225 :lastname => 'Pass',
224 :mail => 'randompass@example.net',
226 :mail => 'randompass@example.net',
225 :language => 'en',
227 :language => 'en',
226 :generate_password => '1',
228 :generate_password => '1',
227 :password => '',
229 :password => '',
228 :password_confirmation => ''
230 :password_confirmation => ''
229 },
231 },
230 :send_information => 1
232 :send_information => 1
231 }
233 }
232 end
234 end
233 user = User.order('id DESC').first
235 user = User.order('id DESC').first
234 assert_equal 'randompass', user.login
236 assert_equal 'randompass', user.login
235
237
236 mail = ActionMailer::Base.deliveries.last
238 mail = ActionMailer::Base.deliveries.last
237 assert_not_nil mail
239 assert_not_nil mail
238 m = mail_body(mail).match(/Password: ([a-zA-Z0-9]+)/)
240 m = mail_body(mail).match(/Password: ([a-zA-Z0-9]+)/)
239 assert m
241 assert m
240 password = m[1]
242 password = m[1]
241 assert user.check_password?(password)
243 assert user.check_password?(password)
242 end
244 end
243
245
244 def test_create_and_continue
246 def test_create_and_continue
245 post :create, :params => {
247 post :create, :params => {
246 :user => {
248 :user => {
247 :login => 'randompass',
249 :login => 'randompass',
248 :firstname => 'Random',
250 :firstname => 'Random',
249 :lastname => 'Pass',
251 :lastname => 'Pass',
250 :mail => 'randompass@example.net',
252 :mail => 'randompass@example.net',
251 :generate_password => '1'
253 :generate_password => '1'
252 },
254 },
253 :continue => '1'
255 :continue => '1'
254 }
256 }
255 assert_redirected_to '/users/new?user%5Bgenerate_password%5D=1'
257 assert_redirected_to '/users/new?user%5Bgenerate_password%5D=1'
256 end
258 end
257
259
258 def test_create_with_failure
260 def test_create_with_failure
259 assert_no_difference 'User.count' do
261 assert_no_difference 'User.count' do
260 post :create, :params => {:user => {}}
262 post :create, :params => {:user => {}}
261 end
263 end
262 assert_response :success
264 assert_response :success
263 assert_select_error /Email cannot be blank/
265 assert_select_error /Email cannot be blank/
264 end
266 end
265
267
266 def test_create_with_failure_sould_preserve_preference
268 def test_create_with_failure_sould_preserve_preference
267 assert_no_difference 'User.count' do
269 assert_no_difference 'User.count' do
268 post :create, :params => {
270 post :create, :params => {
269 :user => {},
271 :user => {},
270 :pref => {
272 :pref => {
271 'no_self_notified' => '1',
273 'no_self_notified' => '1',
272 'hide_mail' => '1',
274 'hide_mail' => '1',
273 'time_zone' => 'Paris',
275 'time_zone' => 'Paris',
274 'comments_sorting' => 'desc',
276 'comments_sorting' => 'desc',
275 'warn_on_leaving_unsaved' => '0'
277 'warn_on_leaving_unsaved' => '0'
276 }
278 }
277 }
279 }
278 end
280 end
279 assert_response :success
281 assert_response :success
280
282
281 assert_select 'select#pref_time_zone option[selected=selected]', :text => /Paris/
283 assert_select 'select#pref_time_zone option[selected=selected]', :text => /Paris/
282 assert_select 'input#pref_no_self_notified[value="1"][checked=checked]'
284 assert_select 'input#pref_no_self_notified[value="1"][checked=checked]'
283 end
285 end
284
286
285 def test_create_admin_should_send_security_notification
287 def test_create_admin_should_send_security_notification
286 ActionMailer::Base.deliveries.clear
288 ActionMailer::Base.deliveries.clear
287 post :create, :params => {
289 post :create, :params => {
288 :user => {
290 :user => {
289 :firstname => 'Edgar',
291 :firstname => 'Edgar',
290 :lastname => 'Schmoe',
292 :lastname => 'Schmoe',
291 :login => 'eschmoe',
293 :login => 'eschmoe',
292 :password => 'secret123',
294 :password => 'secret123',
293 :password_confirmation => 'secret123',
295 :password_confirmation => 'secret123',
294 :mail => 'eschmoe@example.foo',
296 :mail => 'eschmoe@example.foo',
295 :admin => '1'
297 :admin => '1'
296 }
298 }
297 }
299 }
298
300
299 assert_not_nil (mail = ActionMailer::Base.deliveries.last)
301 assert_not_nil (mail = ActionMailer::Base.deliveries.last)
300 assert_mail_body_match '0.0.0.0', mail
302 assert_mail_body_match '0.0.0.0', mail
301 assert_mail_body_match I18n.t(:mail_body_security_notification_add, field: I18n.t(:field_admin), value: 'eschmoe'), mail
303 assert_mail_body_match I18n.t(:mail_body_security_notification_add, field: I18n.t(:field_admin), value: 'eschmoe'), mail
302 assert_select_email do
304 assert_select_email do
303 assert_select 'a[href^=?]', 'http://localhost:3000/users', :text => 'Users'
305 assert_select 'a[href^=?]', 'http://localhost:3000/users', :text => 'Users'
304 end
306 end
305
307
306 # All admins should receive this
308 # All admins should receive this
307 User.where(admin: true, status: Principal::STATUS_ACTIVE).each do |admin|
309 User.where(admin: true, status: Principal::STATUS_ACTIVE).each do |admin|
308 assert_not_nil ActionMailer::Base.deliveries.detect{|mail| [mail.bcc, mail.cc].flatten.include?(admin.mail) }
310 assert_not_nil ActionMailer::Base.deliveries.detect{|mail| [mail.bcc, mail.cc].flatten.include?(admin.mail) }
309 end
311 end
310 end
312 end
311
313
312 def test_create_non_admin_should_not_send_security_notification
314 def test_create_non_admin_should_not_send_security_notification
313 ActionMailer::Base.deliveries.clear
315 ActionMailer::Base.deliveries.clear
314 post :create, :params => {
316 post :create, :params => {
315 :user => {
317 :user => {
316 :firstname => 'Edgar',
318 :firstname => 'Edgar',
317 :lastname => 'Schmoe',
319 :lastname => 'Schmoe',
318 :login => 'eschmoe',
320 :login => 'eschmoe',
319 :password => 'secret123',
321 :password => 'secret123',
320 :password_confirmation => 'secret123',
322 :password_confirmation => 'secret123',
321 :mail => 'eschmoe@example.foo',
323 :mail => 'eschmoe@example.foo',
322 :admin => '0'
324 :admin => '0'
323 }
325 }
324 }
326 }
325 assert_nil ActionMailer::Base.deliveries.last
327 assert_nil ActionMailer::Base.deliveries.last
326 end
328 end
327
329
328
330
329 def test_edit
331 def test_edit
330 get :edit, :params => {:id => 2}
332 get :edit, :params => {:id => 2}
331 assert_response :success
333 assert_response :success
332 assert_select 'input[name=?][value=?]', 'user[login]', 'jsmith'
334 assert_select 'input[name=?][value=?]', 'user[login]', 'jsmith'
333 end
335 end
334
336
335 def test_edit_registered_user
337 def test_edit_registered_user
336 assert User.find(2).register!
338 assert User.find(2).register!
337
339
338 get :edit, :params => {:id => 2}
340 get :edit, :params => {:id => 2}
339 assert_response :success
341 assert_response :success
340 assert_select 'a', :text => 'Activate'
342 assert_select 'a', :text => 'Activate'
341 end
343 end
342
344
343 def test_update
345 def test_update
344 ActionMailer::Base.deliveries.clear
346 ActionMailer::Base.deliveries.clear
345 put :update, :params => {
347 put :update, :params => {
346 :id => 2,
348 :id => 2,
347 :user => {:firstname => 'Changed', :mail_notification => 'only_assigned'},
349 :user => {:firstname => 'Changed', :mail_notification => 'only_assigned'},
348 :pref => {:hide_mail => '1', :comments_sorting => 'desc'}
350 :pref => {:hide_mail => '1', :comments_sorting => 'desc'}
349 }
351 }
350 user = User.find(2)
352 user = User.find(2)
351 assert_equal 'Changed', user.firstname
353 assert_equal 'Changed', user.firstname
352 assert_equal 'only_assigned', user.mail_notification
354 assert_equal 'only_assigned', user.mail_notification
353 assert_equal true, user.pref[:hide_mail]
355 assert_equal true, user.pref[:hide_mail]
354 assert_equal 'desc', user.pref[:comments_sorting]
356 assert_equal 'desc', user.pref[:comments_sorting]
355 assert ActionMailer::Base.deliveries.empty?
357 assert ActionMailer::Base.deliveries.empty?
356 end
358 end
357
359
358 def test_update_with_failure
360 def test_update_with_failure
359 assert_no_difference 'User.count' do
361 assert_no_difference 'User.count' do
360 put :update, :params => {
362 put :update, :params => {
361 :id => 2,
363 :id => 2,
362 :user => {:firstname => ''}
364 :user => {:firstname => ''}
363 }
365 }
364 end
366 end
365 assert_response :success
367 assert_response :success
366 assert_select_error /First name cannot be blank/
368 assert_select_error /First name cannot be blank/
367 end
369 end
368
370
369 def test_update_with_group_ids_should_assign_groups
371 def test_update_with_group_ids_should_assign_groups
370 put :update, :params => {
372 put :update, :params => {
371 :id => 2,
373 :id => 2,
372 :user => {:group_ids => ['10']}
374 :user => {:group_ids => ['10']}
373 }
375 }
374 user = User.find(2)
376 user = User.find(2)
375 assert_equal [10], user.group_ids
377 assert_equal [10], user.group_ids
376 end
378 end
377
379
378 def test_update_with_activation_should_send_a_notification
380 def test_update_with_activation_should_send_a_notification
379 u = User.new(:firstname => 'Foo', :lastname => 'Bar', :mail => 'foo.bar@somenet.foo', :language => 'fr')
381 u = User.new(:firstname => 'Foo', :lastname => 'Bar', :mail => 'foo.bar@somenet.foo', :language => 'fr')
380 u.login = 'foo'
382 u.login = 'foo'
381 u.status = User::STATUS_REGISTERED
383 u.status = User::STATUS_REGISTERED
382 u.save!
384 u.save!
383 ActionMailer::Base.deliveries.clear
385 ActionMailer::Base.deliveries.clear
384 Setting.bcc_recipients = '1'
386 Setting.bcc_recipients = '1'
385
387
386 put :update, :params => {
388 put :update, :params => {
387 :id => u.id,
389 :id => u.id,
388 :user => {:status => User::STATUS_ACTIVE}
390 :user => {:status => User::STATUS_ACTIVE}
389 }
391 }
390 assert u.reload.active?
392 assert u.reload.active?
391 mail = ActionMailer::Base.deliveries.last
393 mail = ActionMailer::Base.deliveries.last
392 assert_not_nil mail
394 assert_not_nil mail
393 assert_equal ['foo.bar@somenet.foo'], mail.bcc
395 assert_equal ['foo.bar@somenet.foo'], mail.bcc
394 assert_mail_body_match ll('fr', :notice_account_activated), mail
396 assert_mail_body_match ll('fr', :notice_account_activated), mail
395 end
397 end
396
398
397 def test_update_with_password_change_should_send_a_notification
399 def test_update_with_password_change_should_send_a_notification
398 ActionMailer::Base.deliveries.clear
400 ActionMailer::Base.deliveries.clear
399 Setting.bcc_recipients = '1'
401 Setting.bcc_recipients = '1'
400
402
401 put :update, :params => {
403 put :update, :params => {
402 :id => 2,
404 :id => 2,
403 :user => {:password => 'newpass123', :password_confirmation => 'newpass123'},
405 :user => {:password => 'newpass123', :password_confirmation => 'newpass123'},
404 :send_information => '1'
406 :send_information => '1'
405 }
407 }
406 u = User.find(2)
408 u = User.find(2)
407 assert u.check_password?('newpass123')
409 assert u.check_password?('newpass123')
408
410
409 mail = ActionMailer::Base.deliveries.last
411 mail = ActionMailer::Base.deliveries.last
410 assert_not_nil mail
412 assert_not_nil mail
411 assert_equal [u.mail], mail.bcc
413 assert_equal [u.mail], mail.bcc
412 assert_mail_body_match 'newpass123', mail
414 assert_mail_body_match 'newpass123', mail
413 end
415 end
414
416
415 def test_update_with_generate_password_should_email_the_password
417 def test_update_with_generate_password_should_email_the_password
416 ActionMailer::Base.deliveries.clear
418 ActionMailer::Base.deliveries.clear
417 Setting.bcc_recipients = '1'
419 Setting.bcc_recipients = '1'
418
420
419 put :update, :params => {
421 put :update, :params => {
420 :id => 2,
422 :id => 2,
421 :user => {
423 :user => {
422 :generate_password => '1',
424 :generate_password => '1',
423 :password => '',
425 :password => '',
424 :password_confirmation => ''
426 :password_confirmation => ''
425 },
427 },
426 :send_information => '1'
428 :send_information => '1'
427 }
429 }
428
430
429 mail = ActionMailer::Base.deliveries.last
431 mail = ActionMailer::Base.deliveries.last
430 assert_not_nil mail
432 assert_not_nil mail
431 m = mail_body(mail).match(/Password: ([a-zA-Z0-9]+)/)
433 m = mail_body(mail).match(/Password: ([a-zA-Z0-9]+)/)
432 assert m
434 assert m
433 password = m[1]
435 password = m[1]
434 assert User.find(2).check_password?(password)
436 assert User.find(2).check_password?(password)
435 end
437 end
436
438
437 def test_update_without_generate_password_should_not_change_password
439 def test_update_without_generate_password_should_not_change_password
438 put :update, :params => {
440 put :update, :params => {
439 :id => 2, :user => {
441 :id => 2, :user => {
440 :firstname => 'changed',
442 :firstname => 'changed',
441 :generate_password => '0',
443 :generate_password => '0',
442 :password => '',
444 :password => '',
443 :password_confirmation => ''
445 :password_confirmation => ''
444 },
446 },
445 :send_information => '1'
447 :send_information => '1'
446 }
448 }
447
449
448 user = User.find(2)
450 user = User.find(2)
449 assert_equal 'changed', user.firstname
451 assert_equal 'changed', user.firstname
450 assert user.check_password?('jsmith')
452 assert user.check_password?('jsmith')
451 end
453 end
452
454
453 def test_update_user_switchin_from_auth_source_to_password_authentication
455 def test_update_user_switchin_from_auth_source_to_password_authentication
454 # Configure as auth source
456 # Configure as auth source
455 u = User.find(2)
457 u = User.find(2)
456 u.auth_source = AuthSource.find(1)
458 u.auth_source = AuthSource.find(1)
457 u.save!
459 u.save!
458
460
459 put :update, :params => {
461 put :update, :params => {
460 :id => u.id,
462 :id => u.id,
461 :user => {:auth_source_id => '', :password => 'newpass123', :password_confirmation => 'newpass123'}
463 :user => {:auth_source_id => '', :password => 'newpass123', :password_confirmation => 'newpass123'}
462 }
464 }
463
465
464 assert_equal nil, u.reload.auth_source
466 assert_equal nil, u.reload.auth_source
465 assert u.check_password?('newpass123')
467 assert u.check_password?('newpass123')
466 end
468 end
467
469
468 def test_update_notified_project
470 def test_update_notified_project
469 get :edit, :params => {:id => 2}
471 get :edit, :params => {:id => 2}
470 assert_response :success
472 assert_response :success
471 u = User.find(2)
473 u = User.find(2)
472 assert_equal [1, 2, 5], u.projects.collect{|p| p.id}.sort
474 assert_equal [1, 2, 5], u.projects.collect{|p| p.id}.sort
473 assert_equal [1, 2, 5], u.notified_projects_ids.sort
475 assert_equal [1, 2, 5], u.notified_projects_ids.sort
474 assert_select 'input[name=?][value=?]', 'user[notified_project_ids][]', '1'
476 assert_select 'input[name=?][value=?]', 'user[notified_project_ids][]', '1'
475 assert_equal 'all', u.mail_notification
477 assert_equal 'all', u.mail_notification
476 put :update, :params => {
478 put :update, :params => {
477 :id => 2,
479 :id => 2,
478 :user => {
480 :user => {
479 :mail_notification => 'selected',
481 :mail_notification => 'selected',
480 :notified_project_ids => [1, 2]
482 :notified_project_ids => [1, 2]
481 }
483 }
482 }
484 }
483 u = User.find(2)
485 u = User.find(2)
484 assert_equal 'selected', u.mail_notification
486 assert_equal 'selected', u.mail_notification
485 assert_equal [1, 2], u.notified_projects_ids.sort
487 assert_equal [1, 2], u.notified_projects_ids.sort
486 end
488 end
487
489
488 def test_update_status_should_not_update_attributes
490 def test_update_status_should_not_update_attributes
489 user = User.find(2)
491 user = User.find(2)
490 user.pref[:no_self_notified] = '1'
492 user.pref[:no_self_notified] = '1'
491 user.pref.save
493 user.pref.save
492
494
493 put :update, :params => {
495 put :update, :params => {
494 :id => 2,
496 :id => 2,
495 :user => {:status => 3}
497 :user => {:status => 3}
496 }
498 }
497 assert_response 302
499 assert_response 302
498 user = User.find(2)
500 user = User.find(2)
499 assert_equal 3, user.status
501 assert_equal 3, user.status
500 assert_equal '1', user.pref[:no_self_notified]
502 assert_equal '1', user.pref[:no_self_notified]
501 end
503 end
502
504
503 def test_update_assign_admin_should_send_security_notification
505 def test_update_assign_admin_should_send_security_notification
504 ActionMailer::Base.deliveries.clear
506 ActionMailer::Base.deliveries.clear
505 put :update, :params => {
507 put :update, :params => {
506 :id => 2,
508 :id => 2,
507 :user => {:admin => 1}
509 :user => {:admin => 1}
508 }
510 }
509
511
510 assert_not_nil (mail = ActionMailer::Base.deliveries.last)
512 assert_not_nil (mail = ActionMailer::Base.deliveries.last)
511 assert_mail_body_match I18n.t(:mail_body_security_notification_add, field: I18n.t(:field_admin), value: User.find(2).login), mail
513 assert_mail_body_match I18n.t(:mail_body_security_notification_add, field: I18n.t(:field_admin), value: User.find(2).login), mail
512
514
513 # All admins should receive this
515 # All admins should receive this
514 User.where(admin: true, status: Principal::STATUS_ACTIVE).each do |admin|
516 User.where(admin: true, status: Principal::STATUS_ACTIVE).each do |admin|
515 assert_not_nil ActionMailer::Base.deliveries.detect{|mail| [mail.bcc, mail.cc].flatten.include?(admin.mail) }
517 assert_not_nil ActionMailer::Base.deliveries.detect{|mail| [mail.bcc, mail.cc].flatten.include?(admin.mail) }
516 end
518 end
517 end
519 end
518
520
519 def test_update_unassign_admin_should_send_security_notification
521 def test_update_unassign_admin_should_send_security_notification
520 user = User.find(2)
522 user = User.find(2)
521 user.admin = true
523 user.admin = true
522 user.save!
524 user.save!
523
525
524 ActionMailer::Base.deliveries.clear
526 ActionMailer::Base.deliveries.clear
525 put :update, :params => {
527 put :update, :params => {
526 :id => user.id,
528 :id => user.id,
527 :user => {:admin => 0}
529 :user => {:admin => 0}
528 }
530 }
529
531
530 assert_not_nil (mail = ActionMailer::Base.deliveries.last)
532 assert_not_nil (mail = ActionMailer::Base.deliveries.last)
531 assert_mail_body_match I18n.t(:mail_body_security_notification_remove, field: I18n.t(:field_admin), value: user.login), mail
533 assert_mail_body_match I18n.t(:mail_body_security_notification_remove, field: I18n.t(:field_admin), value: user.login), mail
532
534
533 # All admins should receive this
535 # All admins should receive this
534 User.where(admin: true, status: Principal::STATUS_ACTIVE).each do |admin|
536 User.where(admin: true, status: Principal::STATUS_ACTIVE).each do |admin|
535 assert_not_nil ActionMailer::Base.deliveries.detect{|mail| [mail.bcc, mail.cc].flatten.include?(admin.mail) }
537 assert_not_nil ActionMailer::Base.deliveries.detect{|mail| [mail.bcc, mail.cc].flatten.include?(admin.mail) }
536 end
538 end
537 end
539 end
538
540
539 def test_update_lock_admin_should_send_security_notification
541 def test_update_lock_admin_should_send_security_notification
540 user = User.find(2)
542 user = User.find(2)
541 user.admin = true
543 user.admin = true
542 user.save!
544 user.save!
543
545
544 ActionMailer::Base.deliveries.clear
546 ActionMailer::Base.deliveries.clear
545 put :update, :params => {
547 put :update, :params => {
546 :id => 2,
548 :id => 2,
547 :user => {:status => Principal::STATUS_LOCKED}
549 :user => {:status => Principal::STATUS_LOCKED}
548 }
550 }
549
551
550 assert_not_nil (mail = ActionMailer::Base.deliveries.last)
552 assert_not_nil (mail = ActionMailer::Base.deliveries.last)
551 assert_mail_body_match I18n.t(:mail_body_security_notification_remove, field: I18n.t(:field_admin), value: User.find(2).login), mail
553 assert_mail_body_match I18n.t(:mail_body_security_notification_remove, field: I18n.t(:field_admin), value: User.find(2).login), mail
552
554
553 # All admins should receive this
555 # All admins should receive this
554 User.where(admin: true, status: Principal::STATUS_ACTIVE).each do |admin|
556 User.where(admin: true, status: Principal::STATUS_ACTIVE).each do |admin|
555 assert_not_nil ActionMailer::Base.deliveries.detect{|mail| [mail.bcc, mail.cc].flatten.include?(admin.mail) }
557 assert_not_nil ActionMailer::Base.deliveries.detect{|mail| [mail.bcc, mail.cc].flatten.include?(admin.mail) }
556 end
558 end
557
559
558 # if user is already locked, destroying should not send a second mail
560 # if user is already locked, destroying should not send a second mail
559 # (for active admins see furtherbelow)
561 # (for active admins see furtherbelow)
560 ActionMailer::Base.deliveries.clear
562 ActionMailer::Base.deliveries.clear
561 delete :destroy, :params => {:id => 1}
563 delete :destroy, :params => {:id => 1}
562 assert_nil ActionMailer::Base.deliveries.last
564 assert_nil ActionMailer::Base.deliveries.last
563
565
564 end
566 end
565
567
566 def test_update_unlock_admin_should_send_security_notification
568 def test_update_unlock_admin_should_send_security_notification
567 user = User.find(5) # already locked
569 user = User.find(5) # already locked
568 user.admin = true
570 user.admin = true
569 user.save!
571 user.save!
570 ActionMailer::Base.deliveries.clear
572 ActionMailer::Base.deliveries.clear
571 put :update, :params => {
573 put :update, :params => {
572 :id => user.id,
574 :id => user.id,
573 :user => {:status => Principal::STATUS_ACTIVE}
575 :user => {:status => Principal::STATUS_ACTIVE}
574 }
576 }
575
577
576 assert_not_nil (mail = ActionMailer::Base.deliveries.last)
578 assert_not_nil (mail = ActionMailer::Base.deliveries.last)
577 assert_mail_body_match I18n.t(:mail_body_security_notification_add, field: I18n.t(:field_admin), value: user.login), mail
579 assert_mail_body_match I18n.t(:mail_body_security_notification_add, field: I18n.t(:field_admin), value: user.login), mail
578
580
579 # All admins should receive this
581 # All admins should receive this
580 User.where(admin: true, status: Principal::STATUS_ACTIVE).each do |admin|
582 User.where(admin: true, status: Principal::STATUS_ACTIVE).each do |admin|
581 assert_not_nil ActionMailer::Base.deliveries.detect{|mail| [mail.bcc, mail.cc].flatten.include?(admin.mail) }
583 assert_not_nil ActionMailer::Base.deliveries.detect{|mail| [mail.bcc, mail.cc].flatten.include?(admin.mail) }
582 end
584 end
583 end
585 end
584
586
585 def test_update_admin_unrelated_property_should_not_send_security_notification
587 def test_update_admin_unrelated_property_should_not_send_security_notification
586 ActionMailer::Base.deliveries.clear
588 ActionMailer::Base.deliveries.clear
587 put :update, :params => {
589 put :update, :params => {
588 :id => 1,
590 :id => 1,
589 :user => {:firstname => 'Jimmy'}
591 :user => {:firstname => 'Jimmy'}
590 }
592 }
591 assert_nil ActionMailer::Base.deliveries.last
593 assert_nil ActionMailer::Base.deliveries.last
592 end
594 end
593
595
594 def test_destroy
596 def test_destroy
595 assert_difference 'User.count', -1 do
597 assert_difference 'User.count', -1 do
596 delete :destroy, :params => {:id => 2}
598 delete :destroy, :params => {:id => 2}
597 end
599 end
598 assert_redirected_to '/users'
600 assert_redirected_to '/users'
599 assert_nil User.find_by_id(2)
601 assert_nil User.find_by_id(2)
600 end
602 end
601
603
602 def test_destroy_should_be_denied_for_non_admin_users
604 def test_destroy_should_be_denied_for_non_admin_users
603 @request.session[:user_id] = 3
605 @request.session[:user_id] = 3
604
606
605 assert_no_difference 'User.count' do
607 assert_no_difference 'User.count' do
606 get :destroy, :params => {:id => 2}
608 get :destroy, :params => {:id => 2}
607 end
609 end
608 assert_response 403
610 assert_response 403
609 end
611 end
610
612
611 def test_destroy_should_redirect_to_back_url_param
613 def test_destroy_should_redirect_to_back_url_param
612 assert_difference 'User.count', -1 do
614 assert_difference 'User.count', -1 do
613 delete :destroy, :params => {:id => 2, :back_url => '/users?name=foo'}
615 delete :destroy, :params => {:id => 2, :back_url => '/users?name=foo'}
614 end
616 end
615 assert_redirected_to '/users?name=foo'
617 assert_redirected_to '/users?name=foo'
616 end
618 end
617
619
618 def test_destroy_active_admin_should_send_security_notification
620 def test_destroy_active_admin_should_send_security_notification
619 user = User.find(2)
621 user = User.find(2)
620 user.admin = true
622 user.admin = true
621 user.save!
623 user.save!
622 ActionMailer::Base.deliveries.clear
624 ActionMailer::Base.deliveries.clear
623 delete :destroy, :params => {:id => user.id}
625 delete :destroy, :params => {:id => user.id}
624
626
625 assert_not_nil (mail = ActionMailer::Base.deliveries.last)
627 assert_not_nil (mail = ActionMailer::Base.deliveries.last)
626 assert_mail_body_match I18n.t(:mail_body_security_notification_remove, field: I18n.t(:field_admin), value: user.login), mail
628 assert_mail_body_match I18n.t(:mail_body_security_notification_remove, field: I18n.t(:field_admin), value: user.login), mail
627
629
628 # All admins should receive this
630 # All admins should receive this
629 User.where(admin: true, status: Principal::STATUS_ACTIVE).each do |admin|
631 User.where(admin: true, status: Principal::STATUS_ACTIVE).each do |admin|
630 assert_not_nil ActionMailer::Base.deliveries.detect{|mail| [mail.bcc, mail.cc].flatten.include?(admin.mail) }
632 assert_not_nil ActionMailer::Base.deliveries.detect{|mail| [mail.bcc, mail.cc].flatten.include?(admin.mail) }
631 end
633 end
632 end
634 end
633 end
635 end
@@ -1,174 +1,192
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.expand_path('../../test_helper', __FILE__)
18 require File.expand_path('../../test_helper', __FILE__)
19
19
20 class WelcomeControllerTest < Redmine::ControllerTest
20 class WelcomeControllerTest < Redmine::ControllerTest
21 fixtures :projects, :news, :users, :members
21 fixtures :projects, :news, :users, :members
22
22
23 def setup
23 def setup
24 Setting.default_language = 'en'
24 Setting.default_language = 'en'
25 User.current = nil
25 User.current = nil
26 end
26 end
27
27
28 def test_index
28 def test_index
29 get :index
29 get :index
30 assert_response :success
30 assert_response :success
31 assert_select 'h3', :text => 'Latest news'
31 assert_select 'h3', :text => 'Latest news'
32 end
32 end
33
33
34 def test_browser_language
34 def test_browser_language
35 @request.env['HTTP_ACCEPT_LANGUAGE'] = 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'
35 @request.env['HTTP_ACCEPT_LANGUAGE'] = 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'
36 get :index
36 get :index
37 assert_select 'html[lang=fr]'
37 assert_select 'html[lang=fr]'
38 end
38 end
39
39
40 def test_browser_language_alternate
40 def test_browser_language_alternate
41 @request.env['HTTP_ACCEPT_LANGUAGE'] = 'zh-TW'
41 @request.env['HTTP_ACCEPT_LANGUAGE'] = 'zh-TW'
42 get :index
42 get :index
43 assert_select 'html[lang=zh-TW]'
43 assert_select 'html[lang=zh-TW]'
44 end
44 end
45
45
46 def test_browser_language_alternate_not_valid
46 def test_browser_language_alternate_not_valid
47 @request.env['HTTP_ACCEPT_LANGUAGE'] = 'fr-CA'
47 @request.env['HTTP_ACCEPT_LANGUAGE'] = 'fr-CA'
48 get :index
48 get :index
49 assert_select 'html[lang=fr]'
49 assert_select 'html[lang=fr]'
50 end
50 end
51
51
52 def test_browser_language_should_be_ignored_with_force_default_language_for_anonymous
52 def test_browser_language_should_be_ignored_with_force_default_language_for_anonymous
53 @request.env['HTTP_ACCEPT_LANGUAGE'] = 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'
53 @request.env['HTTP_ACCEPT_LANGUAGE'] = 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'
54 with_settings :force_default_language_for_anonymous => '1' do
54 with_settings :force_default_language_for_anonymous => '1' do
55 get :index
55 get :index
56 assert_select 'html[lang=en]'
56 assert_select 'html[lang=en]'
57 end
57 end
58 end
58 end
59
59
60 def test_user_language_should_be_used
60 def test_user_language_should_be_used
61 user = User.find(2).update_attribute :language, 'it'
61 user = User.find(2).update_attribute :language, 'it'
62 @request.session[:user_id] = 2
62 @request.session[:user_id] = 2
63 @request.env['HTTP_ACCEPT_LANGUAGE'] = 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'
63 @request.env['HTTP_ACCEPT_LANGUAGE'] = 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'
64 with_settings :default_language => 'fi' do
64 with_settings :default_language => 'fi' do
65 get :index
65 get :index
66 assert_select 'html[lang=it]'
66 assert_select 'html[lang=it]'
67 end
67 end
68 end
68 end
69
69
70 def test_user_language_should_be_ignored_if_force_default_language_for_loggedin
70 def test_user_language_should_be_ignored_if_force_default_language_for_loggedin
71 user = User.find(2).update_attribute :language, 'it'
71 user = User.find(2).update_attribute :language, 'it'
72 @request.session[:user_id] = 2
72 @request.session[:user_id] = 2
73 @request.env['HTTP_ACCEPT_LANGUAGE'] = 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'
73 @request.env['HTTP_ACCEPT_LANGUAGE'] = 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3'
74 with_settings :force_default_language_for_loggedin => '1', :default_language => 'fi' do
74 with_settings :force_default_language_for_loggedin => '1', :default_language => 'fi' do
75 get :index
75 get :index
76 assert_select 'html[lang=fi]'
76 assert_select 'html[lang=fi]'
77 end
77 end
78 end
78 end
79
79
80 def test_robots
80 def test_robots
81 get :robots
81 get :robots
82 assert_response :success
82 assert_response :success
83 assert_equal 'text/plain', @response.content_type
83 assert_equal 'text/plain', @response.content_type
84 assert @response.body.match(%r{^Disallow: /projects/ecookbook/issues\r?$})
84 assert @response.body.match(%r{^Disallow: /projects/ecookbook/issues\r?$})
85 end
85 end
86
86
87 def test_warn_on_leaving_unsaved_turn_on
87 def test_warn_on_leaving_unsaved_turn_on
88 user = User.find(2)
88 user = User.find(2)
89 user.pref.warn_on_leaving_unsaved = '1'
89 user.pref.warn_on_leaving_unsaved = '1'
90 user.pref.save!
90 user.pref.save!
91 @request.session[:user_id] = 2
91 @request.session[:user_id] = 2
92
92
93 get :index
93 get :index
94 assert_select 'script', :text => %r{warnLeavingUnsaved}
94 assert_select 'script', :text => %r{warnLeavingUnsaved}
95 end
95 end
96
96
97 def test_warn_on_leaving_unsaved_turn_off
97 def test_warn_on_leaving_unsaved_turn_off
98 user = User.find(2)
98 user = User.find(2)
99 user.pref.warn_on_leaving_unsaved = '0'
99 user.pref.warn_on_leaving_unsaved = '0'
100 user.pref.save!
100 user.pref.save!
101 @request.session[:user_id] = 2
101 @request.session[:user_id] = 2
102
102
103 get :index
103 get :index
104 assert_select 'script', :text => %r{warnLeavingUnsaved}, :count => 0
104 assert_select 'script', :text => %r{warnLeavingUnsaved}, :count => 0
105 end
105 end
106
106
107 def test_textarea_font_set_to_monospace
108 user = User.find(1)
109 user.pref.textarea_font = 'monospace'
110 user.pref.save!
111 @request.session[:user_id] = 1
112 get :index
113 assert_select 'body.textarea-monospace'
114 end
115
116 def test_textarea_font_set_to_proportional
117 user = User.find(1)
118 user.pref.textarea_font = 'proportional'
119 user.pref.save!
120 @request.session[:user_id] = 1
121 get :index
122 assert_select 'body.textarea-proportional'
123 end
124
107 def test_logout_link_should_post
125 def test_logout_link_should_post
108 @request.session[:user_id] = 2
126 @request.session[:user_id] = 2
109
127
110 get :index
128 get :index
111 assert_select 'a[href="/logout"][data-method=post]', :text => 'Sign out'
129 assert_select 'a[href="/logout"][data-method=post]', :text => 'Sign out'
112 end
130 end
113
131
114 def test_call_hook_mixed_in
132 def test_call_hook_mixed_in
115 assert @controller.respond_to?(:call_hook)
133 assert @controller.respond_to?(:call_hook)
116 end
134 end
117
135
118 def test_project_jump_box_should_escape_names_once
136 def test_project_jump_box_should_escape_names_once
119 Project.find(1).update_attribute :name, 'Foo & Bar'
137 Project.find(1).update_attribute :name, 'Foo & Bar'
120 @request.session[:user_id] = 2
138 @request.session[:user_id] = 2
121
139
122 get :index
140 get :index
123 assert_select "#header select" do
141 assert_select "#header select" do
124 assert_select "option", :text => 'Foo & Bar'
142 assert_select "option", :text => 'Foo & Bar'
125 end
143 end
126 end
144 end
127
145
128 def test_api_offset_and_limit_without_params
146 def test_api_offset_and_limit_without_params
129 assert_equal [0, 25], @controller.api_offset_and_limit({})
147 assert_equal [0, 25], @controller.api_offset_and_limit({})
130 end
148 end
131
149
132 def test_api_offset_and_limit_with_limit
150 def test_api_offset_and_limit_with_limit
133 assert_equal [0, 30], @controller.api_offset_and_limit({:limit => 30})
151 assert_equal [0, 30], @controller.api_offset_and_limit({:limit => 30})
134 assert_equal [0, 100], @controller.api_offset_and_limit({:limit => 120})
152 assert_equal [0, 100], @controller.api_offset_and_limit({:limit => 120})
135 assert_equal [0, 25], @controller.api_offset_and_limit({:limit => -10})
153 assert_equal [0, 25], @controller.api_offset_and_limit({:limit => -10})
136 end
154 end
137
155
138 def test_api_offset_and_limit_with_offset
156 def test_api_offset_and_limit_with_offset
139 assert_equal [10, 25], @controller.api_offset_and_limit({:offset => 10})
157 assert_equal [10, 25], @controller.api_offset_and_limit({:offset => 10})
140 assert_equal [0, 25], @controller.api_offset_and_limit({:offset => -10})
158 assert_equal [0, 25], @controller.api_offset_and_limit({:offset => -10})
141 end
159 end
142
160
143 def test_api_offset_and_limit_with_offset_and_limit
161 def test_api_offset_and_limit_with_offset_and_limit
144 assert_equal [10, 50], @controller.api_offset_and_limit({:offset => 10, :limit => 50})
162 assert_equal [10, 50], @controller.api_offset_and_limit({:offset => 10, :limit => 50})
145 end
163 end
146
164
147 def test_api_offset_and_limit_with_page
165 def test_api_offset_and_limit_with_page
148 assert_equal [0, 25], @controller.api_offset_and_limit({:page => 1})
166 assert_equal [0, 25], @controller.api_offset_and_limit({:page => 1})
149 assert_equal [50, 25], @controller.api_offset_and_limit({:page => 3})
167 assert_equal [50, 25], @controller.api_offset_and_limit({:page => 3})
150 assert_equal [0, 25], @controller.api_offset_and_limit({:page => 0})
168 assert_equal [0, 25], @controller.api_offset_and_limit({:page => 0})
151 assert_equal [0, 25], @controller.api_offset_and_limit({:page => -2})
169 assert_equal [0, 25], @controller.api_offset_and_limit({:page => -2})
152 end
170 end
153
171
154 def test_api_offset_and_limit_with_page_and_limit
172 def test_api_offset_and_limit_with_page_and_limit
155 assert_equal [0, 100], @controller.api_offset_and_limit({:page => 1, :limit => 100})
173 assert_equal [0, 100], @controller.api_offset_and_limit({:page => 1, :limit => 100})
156 assert_equal [200, 100], @controller.api_offset_and_limit({:page => 3, :limit => 100})
174 assert_equal [200, 100], @controller.api_offset_and_limit({:page => 3, :limit => 100})
157 end
175 end
158
176
159 def test_unhautorized_exception_with_anonymous_should_redirect_to_login
177 def test_unhautorized_exception_with_anonymous_should_redirect_to_login
160 WelcomeController.any_instance.stubs(:index).raises(::Unauthorized)
178 WelcomeController.any_instance.stubs(:index).raises(::Unauthorized)
161
179
162 get :index
180 get :index
163 assert_response 302
181 assert_response 302
164 assert_redirected_to('/login?back_url='+CGI.escape('http://test.host/'))
182 assert_redirected_to('/login?back_url='+CGI.escape('http://test.host/'))
165 end
183 end
166
184
167 def test_unhautorized_exception_with_anonymous_and_xmlhttprequest_should_respond_with_401_to_anonymous
185 def test_unhautorized_exception_with_anonymous_and_xmlhttprequest_should_respond_with_401_to_anonymous
168 WelcomeController.any_instance.stubs(:index).raises(::Unauthorized)
186 WelcomeController.any_instance.stubs(:index).raises(::Unauthorized)
169
187
170 @request.env["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest"
188 @request.env["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest"
171 get :index
189 get :index
172 assert_response 401
190 assert_response 401
173 end
191 end
174 end
192 end
General Comments 0
You need to be logged in to leave comments. Login now