Merge branch 'master' of git://github.com/edavis10/redmine into journals

This commit is contained in:
Holger Just 2010-06-29 19:27:14 +02:00
commit bcbb328cd2
90 changed files with 1573 additions and 59 deletions

View File

@ -43,6 +43,7 @@ class MembersController < ApplicationController
format.js {
render(:update) {|page|
page.replace_html "tab-content-members", :partial => 'projects/settings/members'
page << 'hideOnLoad()'
members.each {|member| page.visual_effect(:highlight, "member-#{member.id}") }
}
}
@ -69,6 +70,7 @@ class MembersController < ApplicationController
format.js {
render(:update) {|page|
page.replace_html "tab-content-members", :partial => 'projects/settings/members'
page << 'hideOnLoad()'
page.visual_effect(:highlight, "member-#{@member.id}")
}
}
@ -82,7 +84,11 @@ class MembersController < ApplicationController
end
respond_to do |format|
format.html { redirect_to :controller => 'projects', :action => 'settings', :tab => 'members', :id => @project }
format.js { render(:update) {|page| page.replace_html "tab-content-members", :partial => 'projects/settings/members'} }
format.js { render(:update) {|page|
page.replace_html "tab-content-members", :partial => 'projects/settings/members'
page << 'hideOnLoad()'
}
}
end
end

View File

@ -27,7 +27,7 @@ class ProjectsController < ApplicationController
before_filter :authorize, :except => [ :index, :list, :add, :copy, :archive, :unarchive, :destroy, :activity ]
before_filter :authorize_global, :only => :add
before_filter :require_admin, :only => [ :copy, :archive, :unarchive, :destroy ]
accept_key_auth :activity
accept_key_auth :activity, :index
after_filter :only => [:add, :edit, :archive, :unarchive, :destroy] do |controller|
if controller.request.post?

View File

@ -43,7 +43,7 @@ class SearchController < ApplicationController
begin; offset = params[:offset].to_time if params[:offset]; rescue; end
# quick jump to an issue
if @question.match(/^#?(\d+)$/) && Issue.visible.find_by_id($1)
if @question.match(/^#?(\d+)$/) && Issue.visible.find_by_id($1.to_i)
redirect_to :controller => "issues", :action => "show", :id => $1
return
end

View File

@ -225,8 +225,11 @@ class TimelogController < ApplicationController
def destroy
(render_404; return) unless @time_entry
(render_403; return) unless @time_entry.editable_by?(User.current)
@time_entry.destroy
flash[:notice] = l(:notice_successful_delete)
if @time_entry.destroy && @time_entry.destroyed?
flash[:notice] = l(:notice_successful_delete)
else
flash[:error] = l(:notice_unable_delete_time_entry)
end
redirect_to :back
rescue ::ActionController::RedirectBackError
redirect_to :action => 'details', :project_id => @time_entry.project

View File

@ -83,7 +83,7 @@ private
replace_ids = [params[:replace]]
end
else
replace_ids = 'watcher'
replace_ids = ['watcher']
end
respond_to do |format|
format.html { redirect_to :back }

View File

@ -141,7 +141,6 @@ class Attachment < ActiveRecord::Base
# :unsaved => array of the files that could not be attached
def self.attach_files(obj, attachments)
attached = []
unsaved = []
if attachments && attachments.is_a?(Hash)
attachments.each_value do |attachment|
file = attachment['file']
@ -150,7 +149,13 @@ class Attachment < ActiveRecord::Base
:file => file,
:description => attachment['description'].to_s.strip,
:author => User.current)
a.new_record? ? (obj.unsaved_attachments << a) : (attached << a)
if a.new_record?
obj.unsaved_attachments ||= []
obj.unsaved_attachments << a
else
attached << a
end
end
end
{:files => attached, :unsaved => obj.unsaved_attachments}

View File

@ -49,7 +49,7 @@ class MailHandler < ActionMailer::Base
logger.info "MailHandler: ignoring email from Redmine emission address [#{sender_email}]" if logger && logger.info
return false
end
@user = User.find_by_mail(sender_email)
@user = User.find_by_mail(sender_email) if sender_email.present?
if @user && !@user.active?
logger.info "MailHandler: ignoring email from non-active user [#{@user.login}]" if logger && logger.info
return false
@ -134,7 +134,7 @@ class MailHandler < ActionMailer::Base
if status && issue.new_statuses_allowed_to(user).include?(status)
issue.status = status
end
issue.subject = email.subject.chomp
issue.subject = email.subject.chomp[0,255]
if issue.subject.blank?
issue.subject = '(no subject)'
end

View File

@ -53,7 +53,7 @@ class User < Principal
attr_protected :login, :admin, :password, :password_confirmation, :hashed_password, :group_ids
validates_presence_of :login, :firstname, :lastname, :mail, :if => Proc.new { |user| !user.is_a?(AnonymousUser) }
validates_uniqueness_of :login, :if => Proc.new { |user| !user.login.blank? }
validates_uniqueness_of :login, :if => Proc.new { |user| !user.login.blank? }, :case_sensitive => false
validates_uniqueness_of :mail, :if => Proc.new { |user| !user.mail.blank? }, :case_sensitive => false
# Login must contain lettres, numbers, underscores only
validates_format_of :login, :with => /^[a-z0-9_\-@\.]*$/i
@ -96,7 +96,7 @@ class User < Principal
def self.try_to_login(login, password)
# Make sure no one can sign in with an empty password
return nil if password.to_s.empty?
user = find(:first, :conditions => ["login=?", login])
user = find_by_login(login)
if user
# user is already in local database
return nil if !user.active?
@ -221,7 +221,19 @@ class User < Principal
@notified_projects_ids = nil
notified_projects_ids
end
# Find a user account by matching the exact login and then a case-insensitive
# version. Exact matches will be given priority.
def self.find_by_login(login)
# force string comparison to be case sensitive on MySQL
type_cast = (ActiveRecord::Base.connection.adapter_name == 'MySQL') ? 'BINARY' : ''
# First look for an exact match
user = first(:conditions => ["#{type_cast} login = ?", login])
# Fail over to case-insensitive if none was found
user ||= first(:conditions => ["#{type_cast} LOWER(login) = ?", login.to_s.downcase])
end
def self.find_by_rss_key(key)
token = Token.find_by_value(key)
token && token.user.active? ? token.user : nil

View File

@ -6,7 +6,7 @@
<tr>
<% day = calendar.startdt
while day <= calendar.enddt %>
<%= "<td class='week-number' title='#{ l(:label_week) }'>#{day.cweek}</td>" if day.cwday == calendar.first_wday %>
<%= "<td class='week-number' title='#{ l(:label_week) }'>#{(day+(11-day.cwday)%7).cweek}</td>" if day.cwday == calendar.first_wday %>
<td class="<%= day.month==calendar.month ? 'even' : 'odd' %><%= ' today' if Date.today == day %>">
<p class="day-num"><%= day.day %></p>
<% calendar.events_on(day).each do |i| %>

View File

@ -10,7 +10,7 @@
<% form_tag({ :controller => 'queries', :action => 'new' }, :id => 'query_form') do %>
<%= hidden_field_tag('project_id', @project.to_param) if @project %>
<div id="query_form_content">
<div id="query_form_content" class="hide-when-print">
<fieldset id="filters" class="collapsible <%= @query.new_record? ? "" : "collapsed" %>">
<legend onclick="toggleFieldset(this);"><%= l(:label_filter_plural) %></legend>
<div style="<%= @query.new_record? ? "" : "display: none;" %>">
@ -33,7 +33,7 @@
</div>
</fieldset>
</div>
<p class="buttons">
<p class="buttons hide-when-print">
<%= link_to_remote l(:button_apply),
{ :url => { :set_filter => 1 },

View File

@ -17,10 +17,10 @@
<% if Setting.rest_api_enabled? %>
<h4><%= l(:label_api_access_key) %></h4>
<p>
<div>
<%= link_to_function(l(:button_show), "$('api-access-key').toggle();")%>
<pre id='api-access-key' class='autoscroll'><%= @user.api_key %></pre>
</p>
</div>
<%= javascript_tag("$('api-access-key').hide();") %>
<p>
<% if @user.api_token %>

View File

@ -1,6 +1,11 @@
<% content_for :header_tags do %>
<%= auto_discovery_link_tag(:atom, {:action => 'index', :format => 'atom', :key => User.current.rss_key}) %>
<% end %>
<div class="contextual">
<%= link_to(l(:label_project_new), {:controller => 'projects', :action => 'add'}, :class => 'icon icon-add') + ' |' if User.current.allowed_to?(:add_project, nil, :global => true) %>
<%= link_to(l(:label_issue_view_all), { :controller => 'issues' }) + ' |' if User.current.allowed_to?(:view_issues, nil, :global => true) %>
<%= link_to(l(:label_overall_spent_time), { :controller => 'time_entries' }) + ' |' if User.current.allowed_to?(:view_time_entries, nil, :global => true) %>
<%= link_to l(:label_overall_activity), { :controller => 'projects', :action => 'activity' }%>
</div>

View File

@ -13,6 +13,7 @@
<h3><%=l(:field_author)%>&nbsp;&nbsp;<%= link_to image_tag('zoom_in.png'), :action => 'issue_report_details', :detail => 'author' %></h3>
<%= render :partial => 'simple', :locals => { :data => @issues_by_author, :field_name => "author_id", :rows => @authors } %>
<br />
<%= call_hook(:view_reports_issue_report_split_content_left, :project => @project) %>
</div>
<div class="splitcontentright">
@ -27,5 +28,6 @@
<h3><%=l(:field_category)%>&nbsp;&nbsp;<%= link_to image_tag('zoom_in.png'), :action => 'issue_report_details', :detail => 'category' %></h3>
<%= render :partial => 'simple', :locals => { :data => @issues_by_category, :field_name => "category_id", :rows => @categories } %>
<br />
<%= call_hook(:view_reports_issue_report_split_content_right, :project => @project) %>
</div>

View File

@ -24,6 +24,6 @@ config.action_controller.session = {
# Skip protect_from_forgery in requests http://m.onkey.org/2007/9/28/csrf-protection-for-your-existing-rails-application
config.action_controller.allow_forgery_protection = false
config.gem "shoulda"
config.gem "shoulda", :version => "~> 2.10.3"
config.gem "edavis10-object_daddy", :lib => "object_daddy"
config.gem "mocha"

View File

@ -896,3 +896,5 @@ bg:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -920,3 +920,5 @@ bs:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -899,3 +899,5 @@ ca:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -902,3 +902,5 @@ cs:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -922,3 +922,5 @@ da:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -175,6 +175,7 @@ de:
notice_account_pending: "Ihr Konto wurde erstellt und wartet jetzt auf die Genehmigung des Administrators."
notice_default_data_loaded: Die Standard-Konfiguration wurde erfolgreich geladen.
notice_unable_delete_version: Die Version konnte nicht gelöscht werden.
notice_unable_delete_time_entry: Der Zeiterfassungseintrag konnte nicht gelöscht werden.
notice_issue_done_ratios_updated: Der Ticket-Fortschritt wurde aktualisiert.
error_can_t_load_default_data: "Die Standard-Konfiguration konnte nicht geladen werden: {{value}}"
@ -646,6 +647,7 @@ de:
label_changes_details: Details aller Änderungen
label_issue_tracking: Tickets
label_spent_time: Aufgewendete Zeit
label_overall_spent_time: Aufgewendete Zeit aller Projekte anzeigen
label_f_hour: "{{value}} Stunde"
label_f_hour_plural: "{{value}} Stunden"
label_time_tracking: Zeiterfassung

View File

@ -902,3 +902,5 @@ el:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

909
config/locales/en-GB.yml Normal file
View File

@ -0,0 +1,909 @@
en-GB:
date:
formats:
# Use the strftime parameters for formats.
# When no format has been given, it uses default.
# You can provide other formats here if you like!
default: "%d/%m/%Y"
short: "%d %b"
long: "%d %B, %Y"
day_names: [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday]
abbr_day_names: [Sun, Mon, Tue, Wed, Thu, Fri, Sat]
# Don't forget the nil at the beginning; there's no such thing as a 0th month
month_names: [~, January, February, March, April, May, June, July, August, September, October, November, December]
abbr_month_names: [~, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec]
# Used in date_select and datime_select.
order: [ :year, :month, :day ]
time:
formats:
default: "%d/%m/%Y %I:%M %p"
time: "%I:%M %p"
short: "%d %b %H:%M"
long: "%d %B, %Y %H:%M"
am: "am"
pm: "pm"
datetime:
distance_in_words:
half_a_minute: "half a minute"
less_than_x_seconds:
one: "less than 1 second"
other: "less than {{count}} seconds"
x_seconds:
one: "1 second"
other: "{{count}} seconds"
less_than_x_minutes:
one: "less than a minute"
other: "less than {{count}} minutes"
x_minutes:
one: "1 minute"
other: "{{count}} minutes"
about_x_hours:
one: "about 1 hour"
other: "about {{count}} hours"
x_days:
one: "1 day"
other: "{{count}} days"
about_x_months:
one: "about 1 month"
other: "about {{count}} months"
x_months:
one: "1 month"
other: "{{count}} months"
about_x_years:
one: "about 1 year"
other: "about {{count}} years"
over_x_years:
one: "over 1 year"
other: "over {{count}} years"
almost_x_years:
one: "almost 1 year"
other: "almost {{count}} years"
number:
currency:
format:
format: "%u%n"
unit: "£"
human:
format:
delimiter: ""
precision: 1
storage_units:
format: "%n %u"
units:
byte:
one: "Byte"
other: "Bytes"
kb: "KB"
mb: "MB"
gb: "GB"
tb: "TB"
# Used in array.to_sentence.
support:
array:
sentence_connector: "and"
skip_last_comma: false
activerecord:
errors:
messages:
inclusion: "is not included in the list"
exclusion: "is reserved"
invalid: "is invalid"
confirmation: "doesn't match confirmation"
accepted: "must be accepted"
empty: "can't be empty"
blank: "can't be blank"
too_long: "is too long (maximum is {{count}} characters)"
too_short: "is too short (minimum is {{count}} characters)"
wrong_length: "is the wrong length (should be {{count}} characters)"
taken: "has already been taken"
not_a_number: "is not a number"
not_a_date: "is not a valid date"
greater_than: "must be greater than {{count}}"
greater_than_or_equal_to: "must be greater than or equal to {{count}}"
equal_to: "must be equal to {{count}}"
less_than: "must be less than {{count}}"
less_than_or_equal_to: "must be less than or equal to {{count}}"
odd: "must be odd"
even: "must be even"
greater_than_start_date: "must be greater than start date"
not_same_project: "doesn't belong to the same project"
circular_dependency: "This relation would create a circular dependency"
actionview_instancetag_blank_option: Please select
general_text_No: 'No'
general_text_Yes: 'Yes'
general_text_no: 'no'
general_text_yes: 'yes'
general_lang_name: 'English (British)'
general_csv_separator: ','
general_csv_decimal_separator: '.'
general_csv_encoding: ISO-8859-1
general_pdf_encoding: ISO-8859-1
general_first_day_of_week: '1'
notice_account_updated: Account was successfully updated.
notice_account_invalid_creditentials: Invalid user or password
notice_account_password_updated: Password was successfully updated.
notice_account_wrong_password: Wrong password
notice_account_register_done: Account was successfully created. To activate your account, click on the link that was emailed to you.
notice_account_unknown_email: Unknown user.
notice_can_t_change_password: This account uses an external authentication source. Impossible to change the password.
notice_account_lost_email_sent: An email with instructions to choose a new password has been sent to you.
notice_account_activated: Your account has been activated. You can now log in.
notice_successful_create: Successful creation.
notice_successful_update: Successful update.
notice_successful_delete: Successful deletion.
notice_successful_connection: Successful connection.
notice_file_not_found: The page you were trying to access doesn't exist or has been removed.
notice_locking_conflict: Data has been updated by another user.
notice_not_authorized: You are not authorised to access this page.
notice_email_sent: "An email was sent to {{value}}"
notice_email_error: "An error occurred while sending mail ({{value}})"
notice_feeds_access_key_reseted: Your RSS access key was reset.
notice_api_access_key_reseted: Your API access key was reset.
notice_failed_to_save_issues: "Failed to save {{count}} issue(s) on {{total}} selected: {{ids}}."
notice_no_issue_selected: "No issue is selected! Please, check the issues you want to edit."
notice_account_pending: "Your account was created and is now pending administrator approval."
notice_default_data_loaded: Default configuration successfully loaded.
notice_unable_delete_version: Unable to delete version.
notice_issue_done_ratios_updated: Issue done ratios updated.
error_can_t_load_default_data: "Default configuration could not be loaded: {{value}}"
error_scm_not_found: "The entry or revision was not found in the repository."
error_scm_command_failed: "An error occurred when trying to access the repository: {{value}}"
error_scm_annotate: "The entry does not exist or can not be annotated."
error_issue_not_found_in_project: 'The issue was not found or does not belong to this project'
error_no_tracker_in_project: 'No tracker is associated to this project. Please check the Project settings.'
error_no_default_issue_status: 'No default issue status is defined. Please check your configuration (Go to "Administration -> Issue statuses").'
error_can_not_reopen_issue_on_closed_version: 'An issue assigned to a closed version can not be reopened'
error_can_not_archive_project: This project can not be archived
error_issue_done_ratios_not_updated: "Issue done ratios not updated."
error_workflow_copy_source: 'Please select a source tracker or role'
error_workflow_copy_target: 'Please select target tracker(s) and role(s)'
warning_attachments_not_saved: "{{count}} file(s) could not be saved."
mail_subject_lost_password: "Your {{value}} password"
mail_body_lost_password: 'To change your password, click on the following link:'
mail_subject_register: "Your {{value}} account activation"
mail_body_register: 'To activate your account, click on the following link:'
mail_body_account_information_external: "You can use your {{value}} account to log in."
mail_body_account_information: Your account information
mail_subject_account_activation_request: "{{value}} account activation request"
mail_body_account_activation_request: "A new user ({{value}}) has registered. The account is pending your approval:"
mail_subject_reminder: "{{count}} issue(s) due in the next days"
mail_body_reminder: "{{count}} issue(s) that are assigned to you are due in the next {{days}} days:"
mail_subject_wiki_content_added: "'{{page}}' wiki page has been added"
mail_body_wiki_content_added: "The '{{page}}' wiki page has been added by {{author}}."
mail_subject_wiki_content_updated: "'{{page}}' wiki page has been updated"
mail_body_wiki_content_updated: "The '{{page}}' wiki page has been updated by {{author}}."
gui_validation_error: 1 error
gui_validation_error_plural: "{{count}} errors"
field_name: Name
field_description: Description
field_summary: Summary
field_is_required: Required
field_firstname: Firstname
field_lastname: Lastname
field_mail: Email
field_filename: File
field_filesize: Size
field_downloads: Downloads
field_author: Author
field_created_on: Created
field_updated_on: Updated
field_field_format: Format
field_is_for_all: For all projects
field_possible_values: Possible values
field_regexp: Regular expression
field_min_length: Minimum length
field_max_length: Maximum length
field_value: Value
field_category: Category
field_title: Title
field_project: Project
field_issue: Issue
field_status: Status
field_notes: Notes
field_is_closed: Issue closed
field_is_default: Default value
field_tracker: Tracker
field_subject: Subject
field_due_date: Due date
field_assigned_to: Assigned to
field_priority: Priority
field_fixed_version: Target version
field_user: User
field_role: Role
field_homepage: Homepage
field_is_public: Public
field_parent: Subproject of
field_is_in_roadmap: Issues displayed in roadmap
field_login: Login
field_mail_notification: Email notifications
field_admin: Administrator
field_last_login_on: Last connection
field_language: Language
field_effective_date: Date
field_password: Password
field_new_password: New password
field_password_confirmation: Confirmation
field_version: Version
field_type: Type
field_host: Host
field_port: Port
field_account: Account
field_base_dn: Base DN
field_attr_login: Login attribute
field_attr_firstname: Firstname attribute
field_attr_lastname: Lastname attribute
field_attr_mail: Email attribute
field_onthefly: On-the-fly user creation
field_start_date: Start
field_done_ratio: % Done
field_auth_source: Authentication mode
field_hide_mail: Hide my email address
field_comments: Comment
field_url: URL
field_start_page: Start page
field_subproject: Subproject
field_hours: Hours
field_activity: Activity
field_spent_on: Date
field_identifier: Identifier
field_is_filter: Used as a filter
field_issue_to: Related issue
field_delay: Delay
field_assignable: Issues can be assigned to this role
field_redirect_existing_links: Redirect existing links
field_estimated_hours: Estimated time
field_column_names: Columns
field_time_zone: Time zone
field_searchable: Searchable
field_default_value: Default value
field_comments_sorting: Display comments
field_parent_title: Parent page
field_editable: Editable
field_watcher: Watcher
field_identity_url: OpenID URL
field_content: Content
field_group_by: Group results by
field_sharing: Sharing
setting_app_title: Application title
setting_app_subtitle: Application subtitle
setting_welcome_text: Welcome text
setting_default_language: Default language
setting_login_required: Authentication required
setting_self_registration: Self-registration
setting_attachment_max_size: Attachment max. size
setting_issues_export_limit: Issues export limit
setting_mail_from: Emission email address
setting_bcc_recipients: Blind carbon copy recipients (bcc)
setting_plain_text_mail: Plain text mail (no HTML)
setting_host_name: Host name and path
setting_text_formatting: Text formatting
setting_wiki_compression: Wiki history compression
setting_feeds_limit: Feed content limit
setting_default_projects_public: New projects are public by default
setting_autofetch_changesets: Autofetch commits
setting_sys_api_enabled: Enable WS for repository management
setting_commit_ref_keywords: Referencing keywords
setting_commit_fix_keywords: Fixing keywords
setting_autologin: Autologin
setting_date_format: Date format
setting_time_format: Time format
setting_cross_project_issue_relations: Allow cross-project issue relations
setting_issue_list_default_columns: Default columns displayed on the issue list
setting_repositories_encodings: Repositories encodings
setting_commit_logs_encoding: Commit messages encoding
setting_emails_footer: Emails footer
setting_protocol: Protocol
setting_per_page_options: Objects per page options
setting_user_format: Users display format
setting_activity_days_default: Days displayed on project activity
setting_display_subprojects_issues: Display subprojects issues on main projects by default
setting_enabled_scm: Enabled SCM
setting_mail_handler_body_delimiters: "Truncate emails after one of these lines"
setting_mail_handler_api_enabled: Enable WS for incoming emails
setting_mail_handler_api_key: API key
setting_sequential_project_identifiers: Generate sequential project identifiers
setting_gravatar_enabled: Use Gravatar user icons
setting_gravatar_default: Default Gravatar image
setting_diff_max_lines_displayed: Max number of diff lines displayed
setting_file_max_size_displayed: Max size of text files displayed inline
setting_repository_log_display_limit: Maximum number of revisions displayed on file log
setting_openid: Allow OpenID login and registration
setting_password_min_length: Minimum password length
setting_new_project_user_role_id: Role given to a non-admin user who creates a project
setting_default_projects_modules: Default enabled modules for new projects
setting_issue_done_ratio: Calculate the issue done ratio with
setting_issue_done_ratio_issue_field: Use the issue field
setting_issue_done_ratio_issue_status: Use the issue status
setting_start_of_week: Start calendars on
setting_rest_api_enabled: Enable REST web service
setting_cache_formatted_text: Cache formatted text
permission_add_project: Create project
permission_add_subprojects: Create subprojects
permission_edit_project: Edit project
permission_select_project_modules: Select project modules
permission_manage_members: Manage members
permission_manage_project_activities: Manage project activities
permission_manage_versions: Manage versions
permission_manage_categories: Manage issue categories
permission_view_issues: View Issues
permission_add_issues: Add issues
permission_edit_issues: Edit issues
permission_manage_issue_relations: Manage issue relations
permission_add_issue_notes: Add notes
permission_edit_issue_notes: Edit notes
permission_edit_own_issue_notes: Edit own notes
permission_move_issues: Move issues
permission_delete_issues: Delete issues
permission_manage_public_queries: Manage public queries
permission_save_queries: Save queries
permission_view_gantt: View gantt chart
permission_view_calendar: View calendar
permission_view_issue_watchers: View watchers list
permission_add_issue_watchers: Add watchers
permission_delete_issue_watchers: Delete watchers
permission_log_time: Log spent time
permission_view_time_entries: View spent time
permission_edit_time_entries: Edit time logs
permission_edit_own_time_entries: Edit own time logs
permission_manage_news: Manage news
permission_comment_news: Comment news
permission_manage_documents: Manage documents
permission_view_documents: View documents
permission_manage_files: Manage files
permission_view_files: View files
permission_manage_wiki: Manage wiki
permission_rename_wiki_pages: Rename wiki pages
permission_delete_wiki_pages: Delete wiki pages
permission_view_wiki_pages: View wiki
permission_view_wiki_edits: View wiki history
permission_edit_wiki_pages: Edit wiki pages
permission_delete_wiki_pages_attachments: Delete attachments
permission_protect_wiki_pages: Protect wiki pages
permission_manage_repository: Manage repository
permission_browse_repository: Browse repository
permission_view_changesets: View changesets
permission_commit_access: Commit access
permission_manage_boards: Manage boards
permission_view_messages: View messages
permission_add_messages: Post messages
permission_edit_messages: Edit messages
permission_edit_own_messages: Edit own messages
permission_delete_messages: Delete messages
permission_delete_own_messages: Delete own messages
permission_export_wiki_pages: Export wiki pages
project_module_issue_tracking: Issue tracking
project_module_time_tracking: Time tracking
project_module_news: News
project_module_documents: Documents
project_module_files: Files
project_module_wiki: Wiki
project_module_repository: Repository
project_module_boards: Boards
label_user: User
label_user_plural: Users
label_user_new: New user
label_user_anonymous: Anonymous
label_project: Project
label_project_new: New project
label_project_plural: Projects
label_x_projects:
zero: no projects
one: 1 project
other: "{{count}} projects"
label_project_all: All Projects
label_project_latest: Latest projects
label_issue: Issue
label_issue_new: New issue
label_issue_plural: Issues
label_issue_view_all: View all issues
label_issues_by: "Issues by {{value}}"
label_issue_added: Issue added
label_issue_updated: Issue updated
label_document: Document
label_document_new: New document
label_document_plural: Documents
label_document_added: Document added
label_role: Role
label_role_plural: Roles
label_role_new: New role
label_role_and_permissions: Roles and permissions
label_member: Member
label_member_new: New member
label_member_plural: Members
label_tracker: Tracker
label_tracker_plural: Trackers
label_tracker_new: New tracker
label_workflow: Workflow
label_issue_status: Issue status
label_issue_status_plural: Issue statuses
label_issue_status_new: New status
label_issue_category: Issue category
label_issue_category_plural: Issue categories
label_issue_category_new: New category
label_custom_field: Custom field
label_custom_field_plural: Custom fields
label_custom_field_new: New custom field
label_enumerations: Enumerations
label_enumeration_new: New value
label_information: Information
label_information_plural: Information
label_please_login: Please log in
label_register: Register
label_login_with_open_id_option: or login with OpenID
label_password_lost: Lost password
label_home: Home
label_my_page: My page
label_my_account: My account
label_my_projects: My projects
label_administration: Administration
label_login: Sign in
label_logout: Sign out
label_help: Help
label_reported_issues: Reported issues
label_assigned_to_me_issues: Issues assigned to me
label_last_login: Last connection
label_registered_on: Registered on
label_activity: Activity
label_overall_activity: Overall activity
label_user_activity: "{{value}}'s activity"
label_new: New
label_logged_as: Logged in as
label_environment: Environment
label_authentication: Authentication
label_auth_source: Authentication mode
label_auth_source_new: New authentication mode
label_auth_source_plural: Authentication modes
label_subproject_plural: Subprojects
label_subproject_new: New subproject
label_and_its_subprojects: "{{value}} and its subprojects"
label_min_max_length: Min - Max length
label_list: List
label_date: Date
label_integer: Integer
label_float: Float
label_boolean: Boolean
label_string: Text
label_text: Long text
label_attribute: Attribute
label_attribute_plural: Attributes
label_download: "{{count}} Download"
label_download_plural: "{{count}} Downloads"
label_no_data: No data to display
label_change_status: Change status
label_history: History
label_attachment: File
label_attachment_new: New file
label_attachment_delete: Delete file
label_attachment_plural: Files
label_file_added: File added
label_report: Report
label_report_plural: Reports
label_news: News
label_news_new: Add news
label_news_plural: News
label_news_latest: Latest news
label_news_view_all: View all news
label_news_added: News added
label_settings: Settings
label_overview: Overview
label_version: Version
label_version_new: New version
label_version_plural: Versions
label_close_versions: Close completed versions
label_confirmation: Confirmation
label_export_to: 'Also available in:'
label_read: Read...
label_public_projects: Public projects
label_open_issues: open
label_open_issues_plural: open
label_closed_issues: closed
label_closed_issues_plural: closed
label_x_open_issues_abbr_on_total:
zero: 0 open / {{total}}
one: 1 open / {{total}}
other: "{{count}} open / {{total}}"
label_x_open_issues_abbr:
zero: 0 open
one: 1 open
other: "{{count}} open"
label_x_closed_issues_abbr:
zero: 0 closed
one: 1 closed
other: "{{count}} closed"
label_total: Total
label_permissions: Permissions
label_current_status: Current status
label_new_statuses_allowed: New statuses allowed
label_all: all
label_none: none
label_nobody: nobody
label_next: Next
label_previous: Previous
label_used_by: Used by
label_details: Details
label_add_note: Add a note
label_per_page: Per page
label_calendar: Calendar
label_months_from: months from
label_gantt: Gantt
label_internal: Internal
label_last_changes: "last {{count}} changes"
label_change_view_all: View all changes
label_personalize_page: Personalise this page
label_comment: Comment
label_comment_plural: Comments
label_x_comments:
zero: no comments
one: 1 comment
other: "{{count}} comments"
label_comment_add: Add a comment
label_comment_added: Comment added
label_comment_delete: Delete comments
label_query: Custom query
label_query_plural: Custom queries
label_query_new: New query
label_filter_add: Add filter
label_filter_plural: Filters
label_equals: is
label_not_equals: is not
label_in_less_than: in less than
label_in_more_than: in more than
label_greater_or_equal: '>='
label_less_or_equal: '<='
label_in: in
label_today: today
label_all_time: all time
label_yesterday: yesterday
label_this_week: this week
label_last_week: last week
label_last_n_days: "last {{count}} days"
label_this_month: this month
label_last_month: last month
label_this_year: this year
label_date_range: Date range
label_less_than_ago: less than days ago
label_more_than_ago: more than days ago
label_ago: days ago
label_contains: contains
label_not_contains: doesn't contain
label_day_plural: days
label_repository: Repository
label_repository_plural: Repositories
label_browse: Browse
label_modification: "{{count}} change"
label_modification_plural: "{{count}} changes"
label_branch: Branch
label_tag: Tag
label_revision: Revision
label_revision_plural: Revisions
label_revision_id: "Revision {{value}}"
label_associated_revisions: Associated revisions
label_added: added
label_modified: modified
label_copied: copied
label_renamed: renamed
label_deleted: deleted
label_latest_revision: Latest revision
label_latest_revision_plural: Latest revisions
label_view_revisions: View revisions
label_view_all_revisions: View all revisions
label_max_size: Maximum size
label_sort_highest: Move to top
label_sort_higher: Move up
label_sort_lower: Move down
label_sort_lowest: Move to bottom
label_roadmap: Roadmap
label_roadmap_due_in: "Due in {{value}}"
label_roadmap_overdue: "{{value}} late"
label_roadmap_no_issues: No issues for this version
label_search: Search
label_result_plural: Results
label_all_words: All words
label_wiki: Wiki
label_wiki_edit: Wiki edit
label_wiki_edit_plural: Wiki edits
label_wiki_page: Wiki page
label_wiki_page_plural: Wiki pages
label_index_by_title: Index by title
label_index_by_date: Index by date
label_current_version: Current version
label_preview: Preview
label_feed_plural: Feeds
label_changes_details: Details of all changes
label_issue_tracking: Issue tracking
label_spent_time: Spent time
label_f_hour: "{{value}} hour"
label_f_hour_plural: "{{value}} hours"
label_time_tracking: Time tracking
label_change_plural: Changes
label_statistics: Statistics
label_commits_per_month: Commits per month
label_commits_per_author: Commits per author
label_view_diff: View differences
label_diff_inline: inline
label_diff_side_by_side: side by side
label_options: Options
label_copy_workflow_from: Copy workflow from
label_permissions_report: Permissions report
label_watched_issues: Watched issues
label_related_issues: Related issues
label_applied_status: Applied status
label_loading: Loading...
label_relation_new: New relation
label_relation_delete: Delete relation
label_relates_to: related to
label_duplicates: duplicates
label_duplicated_by: duplicated by
label_blocks: blocks
label_blocked_by: blocked by
label_precedes: precedes
label_follows: follows
label_end_to_start: end to start
label_end_to_end: end to end
label_start_to_start: start to start
label_start_to_end: start to end
label_stay_logged_in: Stay logged in
label_disabled: disabled
label_show_completed_versions: Show completed versions
label_me: me
label_board: Forum
label_board_new: New forum
label_board_plural: Forums
label_board_locked: Locked
label_board_sticky: Sticky
label_topic_plural: Topics
label_message_plural: Messages
label_message_last: Last message
label_message_new: New message
label_message_posted: Message added
label_reply_plural: Replies
label_send_information: Send account information to the user
label_year: Year
label_month: Month
label_week: Week
label_date_from: From
label_date_to: To
label_language_based: Based on user's language
label_sort_by: "Sort by {{value}}"
label_send_test_email: Send a test email
label_feeds_access_key: RSS access key
label_missing_feeds_access_key: Missing a RSS access key
label_feeds_access_key_created_on: "RSS access key created {{value}} ago"
label_module_plural: Modules
label_added_time_by: "Added by {{author}} {{age}} ago"
label_updated_time_by: "Updated by {{author}} {{age}} ago"
label_updated_time: "Updated {{value}} ago"
label_jump_to_a_project: Jump to a project...
label_file_plural: Files
label_changeset_plural: Changesets
label_default_columns: Default columns
label_no_change_option: (No change)
label_bulk_edit_selected_issues: Bulk edit selected issues
label_theme: Theme
label_default: Default
label_search_titles_only: Search titles only
label_user_mail_option_all: "For any event on all my projects"
label_user_mail_option_selected: "For any event on the selected projects only..."
label_user_mail_option_none: "Only for things I watch or I'm involved in"
label_user_mail_no_self_notified: "I don't want to be notified of changes that I make myself"
label_registration_activation_by_email: account activation by email
label_registration_manual_activation: manual account activation
label_registration_automatic_activation: automatic account activation
label_display_per_page: "Per page: {{value}}"
label_age: Age
label_change_properties: Change properties
label_general: General
label_more: More
label_scm: SCM
label_plugins: Plugins
label_ldap_authentication: LDAP authentication
label_downloads_abbr: D/L
label_optional_description: Optional description
label_add_another_file: Add another file
label_preferences: Preferences
label_chronological_order: In chronological order
label_reverse_chronological_order: In reverse chronological order
label_planning: Planning
label_incoming_emails: Incoming emails
label_generate_key: Generate a key
label_issue_watchers: Watchers
label_example: Example
label_display: Display
label_sort: Sort
label_ascending: Ascending
label_descending: Descending
label_date_from_to: From {{start}} to {{end}}
label_wiki_content_added: Wiki page added
label_wiki_content_updated: Wiki page updated
label_group: Group
label_group_plural: Groups
label_group_new: New group
label_time_entry_plural: Spent time
label_version_sharing_none: Not shared
label_version_sharing_descendants: With subprojects
label_version_sharing_hierarchy: With project hierarchy
label_version_sharing_tree: With project tree
label_version_sharing_system: With all projects
label_update_issue_done_ratios: Update issue done ratios
label_copy_source: Source
label_copy_target: Target
label_copy_same_as_target: Same as target
label_display_used_statuses_only: Only display statuses that are used by this tracker
label_api_access_key: API access key
label_missing_api_access_key: Missing an API access key
label_api_access_key_created_on: "API access key created {{value}} ago"
button_login: Login
button_submit: Submit
button_save: Save
button_check_all: Check all
button_uncheck_all: Uncheck all
button_delete: Delete
button_create: Create
button_create_and_continue: Create and continue
button_test: Test
button_edit: Edit
button_add: Add
button_change: Change
button_apply: Apply
button_clear: Clear
button_lock: Lock
button_unlock: Unlock
button_download: Download
button_list: List
button_view: View
button_move: Move
button_move_and_follow: Move and follow
button_back: Back
button_cancel: Cancel
button_activate: Activate
button_sort: Sort
button_log_time: Log time
button_rollback: Rollback to this version
button_watch: Watch
button_unwatch: Unwatch
button_reply: Reply
button_archive: Archive
button_unarchive: Unarchive
button_reset: Reset
button_rename: Rename
button_change_password: Change password
button_copy: Copy
button_copy_and_follow: Copy and follow
button_annotate: Annotate
button_update: Update
button_configure: Configure
button_quote: Quote
button_duplicate: Duplicate
button_show: Show
status_active: active
status_registered: registered
status_locked: locked
version_status_open: open
version_status_locked: locked
version_status_closed: closed
field_active: Active
text_select_mail_notifications: Select actions for which email notifications should be sent.
text_regexp_info: eg. ^[A-Z0-9]+$
text_min_max_length_info: 0 means no restriction
text_project_destroy_confirmation: Are you sure you want to delete this project and related data?
text_subprojects_destroy_warning: "Its subproject(s): {{value}} will be also deleted."
text_workflow_edit: Select a role and a tracker to edit the workflow
text_are_you_sure: Are you sure?
text_journal_changed: "{{label}} changed from {{old}} to {{new}}"
text_journal_set_to: "{{label}} set to {{value}}"
text_journal_deleted: "{{label}} deleted ({{old}})"
text_journal_added: "{{label}} {{value}} added"
text_tip_task_begin_day: task beginning this day
text_tip_task_end_day: task ending this day
text_tip_task_begin_end_day: task beginning and ending this day
text_project_identifier_info: 'Only lower case letters (a-z), numbers and dashes are allowed.<br />Once saved, the identifier can not be changed.'
text_caracters_maximum: "{{count}} characters maximum."
text_caracters_minimum: "Must be at least {{count}} characters long."
text_length_between: "Length between {{min}} and {{max}} characters."
text_tracker_no_workflow: No workflow defined for this tracker
text_unallowed_characters: Unallowed characters
text_comma_separated: Multiple values allowed (comma separated).
text_line_separated: Multiple values allowed (one line for each value).
text_issues_ref_in_commit_messages: Referencing and fixing issues in commit messages
text_issue_added: "Issue {{id}} has been reported by {{author}}."
text_issue_updated: "Issue {{id}} has been updated by {{author}}."
text_wiki_destroy_confirmation: Are you sure you want to delete this wiki and all its content?
text_issue_category_destroy_question: "Some issues ({{count}}) are assigned to this category. What do you want to do?"
text_issue_category_destroy_assignments: Remove category assignments
text_issue_category_reassign_to: Reassign issues to this category
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)."
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."
text_load_default_configuration: Load the default configuration
text_status_changed_by_changeset: "Applied in changeset {{value}}."
text_issues_destroy_confirmation: 'Are you sure you want to delete the selected issue(s)?'
text_select_project_modules: 'Select modules to enable for this project:'
text_default_administrator_account_changed: Default administrator account changed
text_file_repository_writable: Attachments directory writable
text_plugin_assets_writable: Plugin assets directory writable
text_rmagick_available: RMagick available (optional)
text_destroy_time_entries_question: "{{hours}} hours were reported on the issues you are about to delete. What do you want to do?"
text_destroy_time_entries: Delete reported hours
text_assign_time_entries_to_project: Assign reported hours to the project
text_reassign_time_entries: 'Reassign reported hours to this issue:'
text_user_wrote: "{{value}} wrote:"
text_enumeration_destroy_question: "{{count}} objects are assigned to this value."
text_enumeration_category_reassign_to: 'Reassign them to this value:'
text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/email.yml and restart the application to enable them."
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."
text_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.'
text_custom_field_possible_values_info: 'One line for each value'
text_wiki_page_destroy_question: "This page has {{descendants}} child page(s) and descendant(s). What do you want to do?"
text_wiki_page_nullify_children: "Keep child pages as root pages"
text_wiki_page_destroy_children: "Delete child pages and all their descendants"
text_wiki_page_reassign_children: "Reassign child pages to this parent page"
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?"
default_role_manager: Manager
default_role_developper: Developer
default_role_reporter: Reporter
default_tracker_bug: Bug
default_tracker_feature: Feature
default_tracker_support: Support
default_issue_status_new: New
default_issue_status_in_progress: In Progress
default_issue_status_resolved: Resolved
default_issue_status_feedback: Feedback
default_issue_status_closed: Closed
default_issue_status_rejected: Rejected
default_doc_category_user: User documentation
default_doc_category_tech: Technical documentation
default_priority_low: Low
default_priority_normal: Normal
default_priority_high: High
default_priority_urgent: Urgent
default_priority_immediate: Immediate
default_activity_design: Design
default_activity_development: Development
enumeration_issue_priorities: Issue priorities
enumeration_doc_categories: Document categories
enumeration_activities: Activities (time tracking)
enumeration_system_activity: System Activity
notice_unable_delete_time_entry: Unable to delete time log entry.
error_can_not_delete_custom_field: Unable to delete custom field
permission_manage_subtasks: Manage subtasks
label_profile: Profile
error_unable_to_connect: Unable to connect ({{value}})
label_overall_spent_time: Overall spent time
error_can_not_remove_role: This role is in use and can not be deleted.
field_principal: Principal
field_parent_issue: Parent task
label_my_page_block: My page block
text_zoom_out: Zoom out
text_zoom_in: Zoom in
error_unable_delete_issue_status: Unable to delete issue status
label_subtask_plural: Subtasks
error_can_not_delete_tracker: This tracker contains issues and can't be deleted.
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
label_project_copy_notifications: Send email notifications during the project copy

View File

@ -153,6 +153,7 @@ en:
notice_account_pending: "Your account was created and is now pending administrator approval."
notice_default_data_loaded: Default configuration successfully loaded.
notice_unable_delete_version: Unable to delete version.
notice_unable_delete_time_entry: Unable to delete time log entry.
notice_issue_done_ratios_updated: Issue done ratios updated.
error_can_t_load_default_data: "Default configuration could not be loaded: {{value}}"
@ -638,6 +639,7 @@ en:
label_changes_details: Details of all changes
label_issue_tracking: Issue tracking
label_spent_time: Spent time
label_overall_spent_time: Overall spent time
label_f_hour: "{{value}} hour"
label_f_hour_plural: "{{value}} hours"
label_time_tracking: Time tracking

View File

@ -946,3 +946,5 @@ es:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -906,3 +906,5 @@ eu:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -932,3 +932,5 @@ fi:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -925,3 +925,5 @@ fr:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -922,3 +922,5 @@ gl:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -906,3 +906,5 @@ he:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -909,3 +909,5 @@ hr:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -929,3 +929,5 @@
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -914,3 +914,5 @@ id:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -909,3 +909,5 @@ it:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -183,6 +183,7 @@ ja:
notice_account_pending: アカウントは作成済みで、管理者の承認待ちです。
notice_default_data_loaded: デフォルト設定をロードしました。
notice_unable_delete_version: バージョンを削除できません
notice_unable_delete_time_entry: 作業時間を削除できません
notice_issue_done_ratios_updated: チケットの進捗が更新されました。
error_can_t_load_default_data: "デフォルト設定がロードできませんでした: {{value}}"
@ -670,6 +671,7 @@ ja:
label_changes_details: 全変更の詳細
label_issue_tracking: チケットトラッキング
label_spent_time: 作業時間の記録
label_overall_spent_time: 全ての作業時間の記録
label_f_hour: "{{value}}時間"
label_f_hour_plural: "{{value}}時間"
label_time_tracking: 時間トラッキング

View File

@ -962,3 +962,5 @@ ko:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -970,3 +970,5 @@ lt:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -897,3 +897,5 @@ lv:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -903,3 +903,5 @@ mn:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -884,3 +884,5 @@ nl:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -897,3 +897,5 @@
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -927,3 +927,5 @@ pl:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -930,3 +930,5 @@ pt-BR:
notice_failed_to_save_members: "Falha ao gravar membro(s): {{errors}}."
text_zoom_out: Afastar zoom
text_zoom_in: Aproximar zoom
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -914,3 +914,5 @@ pt:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -899,3 +899,5 @@ ro:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -1022,3 +1022,5 @@ ru:
field_principal: Глава
text_zoom_out: Отдалить
text_zoom_in: Приблизить
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -901,3 +901,5 @@ sk:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -901,3 +901,5 @@ sl:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -903,3 +903,5 @@ sr-CY:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -903,3 +903,5 @@ sr:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -197,7 +197,8 @@ sv:
notice_email_error: "Ett fel inträffade när mail skickades ({{value}})"
notice_feeds_access_key_reseted: Din RSS-nyckel återställdes.
notice_api_access_key_reseted: Din API-nyckel återställdes.
notice_failed_to_save_issues: "Misslyckades att spara {{count}} ärende(n) på {{total}} valt: {{ids}}."
notice_failed_to_save_issues: "Misslyckades med att spara {{count}} ärende(n) på {{total}} valt: {{ids}}."
notice_failed_to_save_members: "Misslyckades med att spara medlem(mar): {{errors}}."
notice_no_issue_selected: "Inget ärende är markerat! Var vänlig, markera de ärenden du vill ändra."
notice_account_pending: "Ditt konto skapades och avvaktar nu administratörens godkännande."
notice_default_data_loaded: Standardkonfiguration inläst.
@ -277,6 +278,7 @@ sv:
field_priority: Prioritet
field_fixed_version: Versionsmål
field_user: Användare
field_principal: Principal
field_role: Roll
field_homepage: Hemsida
field_is_public: Publik
@ -509,6 +511,7 @@ sv:
label_my_page: Min sida
label_my_account: Mitt konto
label_my_projects: Mina projekt
label_my_page_block: '"Min sida"-block'
label_administration: Administration
label_login: Logga in
label_logout: Logga ut
@ -919,6 +922,8 @@ sv:
text_wiki_page_destroy_children: Ta bort alla underliggande sidor
text_wiki_page_reassign_children: Flytta undersidor till denna föräldersida
text_own_membership_delete_confirmation: "Några av, eller alla, dina behörigheter kommer att tas bort och du kanske inte längre kommer kunna göra ändringar i det här projektet.\nVill du verkligen fortsätta?"
text_zoom_out: Zooma ut
text_zoom_in: Zooma in
default_role_manager: Projektledare
default_role_developper: Utvecklare
@ -946,8 +951,5 @@ sv:
enumeration_doc_categories: Dokumentkategorier
enumeration_activities: Aktiviteter (tidsuppföljning)
enumeration_system_activity: Systemaktivitet
field_principal: Principal
label_my_page_block: My page block
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -899,3 +899,5 @@ th:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -929,3 +929,5 @@ tr:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -898,3 +898,5 @@ uk:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -961,3 +961,5 @@ vi:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -991,3 +991,5 @@
enumeration_doc_categories: 文件分類
enumeration_activities: 活動 (時間追蹤)
enumeration_system_activity: 系統活動
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -924,3 +924,5 @@ zh:
notice_failed_to_save_members: "Failed to save member(s): {{errors}}."
text_zoom_out: Zoom out
text_zoom_in: Zoom in
notice_unable_delete_time_entry: Unable to delete time log entry.
label_overall_spent_time: Overall spent time

View File

@ -8,6 +8,18 @@ http://www.redmine.org/
Adds context menu to the roadmap issue lists
== 2010-06-24 v0.9.5
Linkify folder names on revision view
"fiters" and "options" should be hidden in print view via css
Fixed: NoMethodError when no issue params are submitted
Fixed: projects.atom with required authentication
Fixed: External links not correctly displayed in Wiki TOC
Fixed: Member role forms in project settings are not hidden after member added
Fixed: pre can't be inside p
Fixed: session cookie path does not respect RAILS_RELATIVE_URL_ROOT
Fixed: mail handler fails when the from address is empty
== 2010-05-01 v0.9.4
Filters collapsed by default on issues index page for a saved query

View File

@ -33,7 +33,7 @@ Optional:
4. Generate a session store secret
Redmine stores session data in cookies by default, which requires
a secret to be generated. Run:
rake config/initializers/session_store.rb
rake generate_session_store
5. Create the database structure. Under the application main directory:
rake db:migrate RAILS_ENV="production"

View File

@ -12,12 +12,12 @@ http://www.redmine.org/
2. Copy your database settings (RAILS_ROOT/config/database.yml)
and SMTP settings (RAILS_ROOT/config/email.yml)
into the new config directory
DO NOT REPLACE ANY OTHERS FILES.
DO NOT REPLACE OR EDIT ANY OTHER FILES.
3. Generate a session store secret
Redmine stores session data in cookies by default, which requires
a secret to be generated. Run:
rake config/initializers/session_store.rb
rake generate_session_store
4. Migrate your database (please make a backup before doing this):
rake db:migrate RAILS_ENV="production"

View File

@ -5,4 +5,6 @@ Redmine::Plugin.register :<%= plugin_name %> do
author 'Author name'
description 'This is a plugin for Redmine'
version '0.0.1'
url 'http://example.com/path/to/plugin'
author_url 'http://example.com/about'
end

View File

@ -1,4 +1,6 @@
class <%= class_name %>Controller < ApplicationController
unloadable
<% actions.each do |action| -%>
def <%= action %>

View File

@ -1,2 +1,3 @@
class <%= class_name %> < ActiveRecord::Base
unloadable
end

View File

@ -47,7 +47,7 @@ module Redmine
# Get info about the svn repository
def info
cmd = "#{SVN_BIN} info --xml #{target('')}"
cmd = "#{SVN_BIN} info --xml #{target}"
cmd << credentials_string
info = nil
shellout(cmd) do |io|
@ -77,7 +77,7 @@ module Redmine
path ||= ''
identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD"
entries = Entries.new
cmd = "#{SVN_BIN} list --xml #{target(URI.escape(path))}@#{identifier}"
cmd = "#{SVN_BIN} list --xml #{target(path)}@#{identifier}"
cmd << credentials_string
shellout(cmd) do |io|
output = io.read
@ -116,7 +116,7 @@ module Redmine
return nil unless self.class.client_version_above?([1, 5, 0])
identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD"
cmd = "#{SVN_BIN} proplist --verbose --xml #{target(URI.escape(path))}@#{identifier}"
cmd = "#{SVN_BIN} proplist --verbose --xml #{target(path)}@#{identifier}"
cmd << credentials_string
properties = {}
shellout(cmd) do |io|
@ -142,7 +142,7 @@ module Redmine
cmd << credentials_string
cmd << " --verbose " if options[:with_paths]
cmd << " --limit #{options[:limit].to_i}" if options[:limit]
cmd << ' ' + target(URI.escape(path))
cmd << ' ' + target(path)
shellout(cmd) do |io|
output = io.read
begin
@ -180,7 +180,7 @@ module Redmine
cmd = "#{SVN_BIN} diff -r "
cmd << "#{identifier_to}:"
cmd << "#{identifier_from}"
cmd << " #{target(URI.escape(path))}@#{identifier_from}"
cmd << " #{target(path)}@#{identifier_from}"
cmd << credentials_string
diff = []
shellout(cmd) do |io|
@ -194,7 +194,7 @@ module Redmine
def cat(path, identifier=nil)
identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD"
cmd = "#{SVN_BIN} cat #{target(URI.escape(path))}@#{identifier}"
cmd = "#{SVN_BIN} cat #{target(path)}@#{identifier}"
cmd << credentials_string
cat = nil
shellout(cmd) do |io|
@ -207,7 +207,7 @@ module Redmine
def annotate(path, identifier=nil)
identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD"
cmd = "#{SVN_BIN} blame #{target(URI.escape(path))}@#{identifier}"
cmd = "#{SVN_BIN} blame #{target(path)}@#{identifier}"
cmd << credentials_string
blame = Annotate.new
shellout(cmd) do |io|
@ -243,6 +243,13 @@ module Redmine
end
end
end
def target(path = '')
base = path.match(/^\//) ? root_url : url
uri = "#{base}/#{path}"
uri = URI.escape(URI.escape(uri), '[]')
shell_quote(uri.gsub(/[?<>\*]/, ''))
end
end
end
end

View File

@ -4,7 +4,7 @@ module Redmine
module VERSION #:nodoc:
MAJOR = 0
MINOR = 9
TINY = 4
TINY = 5
# Branch values:
# * official release: nil

View File

@ -65,6 +65,11 @@ module Redmine
def textile_p_withtoc(tag, atts, cite, content)
# removes wiki links from the item
toc_item = content.gsub(/(\[\[([^\]\|]*)(\|([^\]]*))?\]\])/) { $4 || $2 }
# sanitizes titles from links
# see redcloth3.rb, same as "#{pre}#{text}#{post}"
toc_item.gsub!(LINK_RE) { [$2, $4, $9].join }
# sanitizes image links from titles
toc_item.gsub!(IMAGE_RE) { [$5].join }
# removes styles
# eg. %{color:red}Triggers% => Triggers
toc_item.gsub! %r[%\{[^\}]*\}([^%]+)%], '\\1'

View File

@ -25,7 +25,7 @@ class TabularFormBuilder < ActionView::Helpers::FormBuilder
super
end
(field_helpers - %w(radio_button hidden_field) + %w(date_select)).each do |selector|
(field_helpers - %w(radio_button hidden_field fields_for) + %w(date_select)).each do |selector|
src = <<-END_SRC
def #{selector}(field, options = {})
label_for_field(field, options) + super

View File

@ -17,6 +17,13 @@ file 'config/initializers/session_store.rb' do
# you'll be exposed to dictionary attacks.
ActionController::Base.session = {
:session_key => '_redmine_session',
#
# Uncomment and edit the :session_path below if are hosting your Redmine
# at a suburi and don't want the top level path to access the cookies
#
# See: http://www.redmine.org/issues/3968
#
# :session_path => '/url_path_to/your/redmine/',
:secret => '#{secret}'
}
EOF

View File

@ -226,8 +226,10 @@ Ajax.Responders.register({
}
});
Event.observe(window, 'load', function() {
function hideOnLoad() {
$$('.hol').each(function(el) {
el.hide();
});
});
}
Event.observe(window, 'load', hideOnLoad);

View File

@ -1694,15 +1694,27 @@ Date.prototype.getDayOfYear = function() {
return Math.floor(time / Date.DAY);
};
/** Returns the number of the week in year, as defined in ISO 8601. */
/** Returns the number of the week in year, as defined in ISO 8601.
This function is only correct if `this` is the first day of the week. */
Date.prototype.getWeekNumber = function() {
var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
var DoW = d.getDay();
d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu
var ms = d.valueOf(); // GMT
d.setMonth(0);
d.setDate(4); // Thu in Week 1
return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;
var d = new Date(this.getFullYear(), this.getMonth(), this.getDate());
var days = 1000*60*60*24; // one day in milliseconds
// get the thursday of the current week
var this_thursday = new Date(
d.valueOf() // selected date
- (d.getDay() % 7)*days // previous sunday
+ 4*days // + 4 days
).valueOf();
// the thursday in the first week of the year
var first_thursday = new Date(
new Date(this.getFullYear(), 0, 4).valueOf() // January 4 is in the first week by definition
- (d.getDay() % 7)*days // previous sunday
+ 4*days // + 4 days
).valueOf();
return Math.round((this_thursday - first_thursday) / (7*days)) + 1;
};
/** Checks date and time equality */

View File

@ -0,0 +1,127 @@
// ** I18N
// Calendar EN language
// Author: Mihai Bazon, <mihai_bazon@yahoo.com>
// Encoding: any
// Distributed under the same terms as the calendar itself.
// For translators: please use UTF-8 if possible. We strongly believe that
// Unicode is the answer to a real internationalized world. Also please
// include your contact information in the header, as can be seen above.
// full day names
Calendar._DN = new Array
("Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday");
// Please note that the following array of short day names (and the same goes
// for short month names, _SMN) isn't absolutely necessary. We give it here
// for exemplification on how one can customize the short day names, but if
// they are simply the first N letters of the full name you can simply say:
//
// Calendar._SDN_len = N; // short day name length
// Calendar._SMN_len = N; // short month name length
//
// If N = 3 then this is not needed either since we assume a value of 3 if not
// present, to be compatible with translation files that were written before
// this feature.
// short day names
Calendar._SDN = new Array
("Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat",
"Sun");
// First day of the week. "0" means display Sunday first, "1" means display
// Monday first, etc.
Calendar._FD = 1;
// full month names
Calendar._MN = new Array
("January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December");
// short month names
Calendar._SMN = new Array
("Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec");
// tooltips
Calendar._TT = {};
Calendar._TT["INFO"] = "About the calendar";
Calendar._TT["ABOUT"] =
"DHTML Date/Time Selector\n" +
"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-)
"For latest version visit: http://www.dynarch.com/projects/calendar/\n" +
"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." +
"\n\n" +
"Date selection:\n" +
"- Use the \xab, \xbb buttons to select year\n" +
"- Use the " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " buttons to select month\n" +
"- Hold mouse button on any of the above buttons for faster selection.";
Calendar._TT["ABOUT_TIME"] = "\n\n" +
"Time selection:\n" +
"- Click on any of the time parts to increase it\n" +
"- or Shift-click to decrease it\n" +
"- or click and drag for faster selection.";
Calendar._TT["PREV_YEAR"] = "Prev. year (hold for menu)";
Calendar._TT["PREV_MONTH"] = "Prev. month (hold for menu)";
Calendar._TT["GO_TODAY"] = "Go Today";
Calendar._TT["NEXT_MONTH"] = "Next month (hold for menu)";
Calendar._TT["NEXT_YEAR"] = "Next year (hold for menu)";
Calendar._TT["SEL_DATE"] = "Select date";
Calendar._TT["DRAG_TO_MOVE"] = "Drag to move";
Calendar._TT["PART_TODAY"] = " (today)";
// the following is to inform that "%s" is to be the first day of week
// %s will be replaced with the day name.
Calendar._TT["DAY_FIRST"] = "Display %s first";
// This may be locale-dependent. It specifies the week-end days, as an array
// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1
// means Monday, etc.
Calendar._TT["WEEKEND"] = "0,6";
Calendar._TT["CLOSE"] = "Close";
Calendar._TT["TODAY"] = "Today";
Calendar._TT["TIME_PART"] = "(Shift-)Click or drag to change value";
// date formats
Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d";
Calendar._TT["TT_DATE_FORMAT"] = "%a, %e %b";
Calendar._TT["WK"] = "wk";
Calendar._TT["TIME"] = "Time:";

View File

@ -0,0 +1,16 @@
jsToolBar.strings = {};
jsToolBar.strings['Strong'] = 'Strong';
jsToolBar.strings['Italic'] = 'Italic';
jsToolBar.strings['Underline'] = 'Underline';
jsToolBar.strings['Deleted'] = 'Deleted';
jsToolBar.strings['Code'] = 'Inline Code';
jsToolBar.strings['Heading 1'] = 'Heading 1';
jsToolBar.strings['Heading 2'] = 'Heading 2';
jsToolBar.strings['Heading 3'] = 'Heading 3';
jsToolBar.strings['Unordered list'] = 'Unordered list';
jsToolBar.strings['Ordered list'] = 'Ordered list';
jsToolBar.strings['Quote'] = 'Quote';
jsToolBar.strings['Unquote'] = 'Remove Quote';
jsToolBar.strings['Preformatted text'] = 'Preformatted text';
jsToolBar.strings['Wiki link'] = 'Link to a Wiki page';
jsToolBar.strings['Image'] = 'Image';

View File

@ -911,4 +911,5 @@ h2 img { vertical-align:middle; }
#main { background: #fff; }
#content { width: 99%; margin: 0; padding: 0; border: 0; background: #fff; overflow: visible !important;}
#wiki_add_attachment { display:none; }
.hide-when-print { display: none; }
}

View File

@ -12,10 +12,6 @@ class Attachment < ActiveRecord::Base
end
def self.generate_file
@file = 'a_file.png'
@file.stubs(:original_filename).returns('a_file.png')
@file.stubs(:content_type).returns('image/png')
@file.stubs(:read).returns(false)
@file
@file = mock_file
end
end

View File

@ -0,0 +1,17 @@
Return-Path: <john.doe@somenet.foo>
Received: from osiris ([127.0.0.1])
by OSIRIS
with hMailServer ; Sun, 22 Jun 2008 12:28:07 +0200
Message-ID: <000501c8d452$a95cd7e0$0a00a8c0@osiris>
To: <redmine@somenet.foo>
Subject: Ticket by unknown user
Date: Sun, 22 Jun 2008 12:28:07 +0200
MIME-Version: 1.0
Content-Type: text/plain;
format=flowed;
charset="iso-8859-1";
reply-type=original
Content-Transfer-Encoding: 7bit
This is a ticket submitted by an unknown user.

View File

@ -0,0 +1,57 @@
Return-Path: <JSmith@somenet.foo>
Received: from osiris ([127.0.0.1])
by OSIRIS
with hMailServer ; Sun, 22 Jun 2008 12:28:07 +0200
Message-ID: <000501c8d452$a95cd7e0$0a00a8c0@osiris>
From: "John Smith" <JSmith@somenet.foo>
To: <redmine@somenet.foo>
Subject: New ticket on a given project with a very long subject line which exceeds 255 chars and should not be ignored but chopped off. And if the subject line is still not long enough, we just add more text. And more text. Wow, this is really annoying. Especially, if you have nothing to say...
Date: Sun, 22 Jun 2008 12:28:07 +0200
MIME-Version: 1.0
Content-Type: text/plain;
format=flowed;
charset="iso-8859-1";
reply-type=original
Content-Transfer-Encoding: 7bit
X-Priority: 3
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook Express 6.00.2900.2869
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2869
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas imperdiet
turpis et odio. Integer eget pede vel dolor euismod varius. Phasellus
blandit eleifend augue. Nulla facilisi. Duis id diam. Class aptent taciti
sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In
in urna sed tellus aliquet lobortis. Morbi scelerisque tortor in dolor. Cras
sagittis odio eu lacus. Aliquam sem tortor, consequat sit amet, vestibulum
id, iaculis at, lectus. Fusce tortor libero, congue ut, euismod nec, luctus
eget, eros. Pellentesque tortor enim, feugiat in, dignissim eget, tristique
sed, mauris --- Pellentesque habitant morbi tristique senectus et netus et
malesuada fames ac turpis egestas. Quisque sit amet libero. In hac habitasse
platea dictumst.
--- This line starts with a delimiter and should not be stripped
This paragraph is before delimiters.
BREAK
This paragraph is between delimiters.
---
This paragraph is after the delimiter so it shouldn't appear.
Nulla et nunc. Duis pede. Donec et ipsum. Nam ut dui tincidunt neque
sollicitudin iaculis. Duis vitae dolor. Vestibulum eget massa. Sed lorem.
Nullam volutpat cursus erat. Cras felis dolor, lacinia quis, rutrum et,
dictum et, ligula. Sed erat nibh, gravida in, accumsan non, placerat sed,
massa. Sed sodales, ante fermentum ultricies sollicitudin, massa leo
pulvinar dui, a gravida orci mi eget odio. Nunc a lacus.
Project: onlinestore
Status: Resolved
due date: 2010-12-31
Start Date:2010-01-01
Assigned to: John Smith

View File

@ -67,6 +67,8 @@ class AdminControllerTest < ActionController::TestCase
def test_load_default_configuration_data
delete_configuration_data
post :default_configuration, :lang => 'fr'
assert_response :redirect
assert_nil flash[:error]
assert IssueStatus.find_by_name('Nouveau')
end

View File

@ -17,4 +17,48 @@ class CalendarsControllerTest < ActionController::TestCase
assert_not_nil assigns(:calendar)
end
def test_week_number_calculation
Setting.start_of_week = 7
get :show, :month => '1', :year => '2010'
assert_response :success
assert_tag :tag => 'tr',
:descendant => {:tag => 'td',
:attributes => {:class => 'week-number'}, :content => '53'},
:descendant => {:tag => 'td',
:attributes => {:class => 'odd'}, :content => '27'},
:descendant => {:tag => 'td',
:attributes => {:class => 'even'}, :content => '2'}
assert_tag :tag => 'tr',
:descendant => {:tag => 'td',
:attributes => {:class => 'week-number'}, :content => '1'},
:descendant => {:tag => 'td',
:attributes => {:class => 'odd'}, :content => '3'},
:descendant => {:tag => 'td',
:attributes => {:class => 'even'}, :content => '9'}
Setting.start_of_week = 1
get :show, :month => '1', :year => '2010'
assert_response :success
assert_tag :tag => 'tr',
:descendant => {:tag => 'td',
:attributes => {:class => 'week-number'}, :content => '53'},
:descendant => {:tag => 'td',
:attributes => {:class => 'even'}, :content => '28'},
:descendant => {:tag => 'td',
:attributes => {:class => 'even'}, :content => '3'}
assert_tag :tag => 'tr',
:descendant => {:tag => 'td',
:attributes => {:class => 'week-number'}, :content => '1'},
:descendant => {:tag => 'td',
:attributes => {:class => 'even'}, :content => '4'},
:descendant => {:tag => 'td',
:attributes => {:class => 'even'}, :content => '10'}
end
end

View File

@ -47,6 +47,24 @@ class DocumentsControllerTest < ActionController::TestCase
:content => 'Technical documentation'}
end
def test_index_with_long_description
# adds a long description to the first document
doc = documents(:documents_001)
doc.update_attributes(:description => <<LOREM)
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut egestas, mi vehicula varius varius, ipsum massa fermentum orci, eget tristique ante sem vel mi. Nulla facilisi. Donec enim libero, luctus ac sagittis sit amet, vehicula sagittis magna. Duis ultrices molestie ante, eget scelerisque sem iaculis vitae. Etiam fermentum mauris vitae metus pharetra condimentum fermentum est pretium. Proin sollicitudin elementum quam quis pharetra. Aenean facilisis nunc quis elit volutpat mollis. Aenean eleifend varius euismod. Ut dolor est, congue eget dapibus eget, elementum eu odio. Integer et lectus neque, nec scelerisque nisi. EndOfLineHere
Vestibulum non velit mi. Aliquam scelerisque libero ut nulla fringilla a sollicitudin magna rhoncus. Praesent a nunc lorem, ac porttitor eros. Sed ac diam nec neque interdum adipiscing quis quis justo. Donec arcu nunc, fringilla eu dictum at, venenatis ac sem. Vestibulum quis elit urna, ac mattis sapien. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
LOREM
get :index, :project_id => 'ecookbook'
assert_response :success
assert_template 'index'
# should only truncate on new lines to avoid breaking wiki formatting
assert_select '.wiki p', :text => (doc.description.split("\n").first + '...')
assert_select '.wiki p', :text => Regexp.new(Regexp.escape("EndOfLineHere..."))
end
def test_new_with_one_attachment
ActionMailer::Base.deliveries.clear
Setting.notified_events << 'document_added'

View File

@ -60,6 +60,33 @@ class ProjectsControllerTest < ActionController::TestCase
assert_select 'feed>entry', :count => Project.count(:conditions => Project.visible_by(User.current))
end
context "#index" do
context "by non-admin user with view_time_entries permission" do
setup do
@request.session[:user_id] = 3
end
should "show overall spent time link" do
get :index
assert_template 'index'
assert_tag :a, :attributes => {:href => '/time_entries'}
end
end
context "by non-admin user without view_time_entries permission" do
setup do
Role.find(2).remove_permission! :view_time_entries
Role.non_member.remove_permission! :view_time_entries
Role.anonymous.remove_permission! :view_time_entries
@request.session[:user_id] = 3
end
should "not show overall spent time link" do
get :index
assert_template 'index'
assert_no_tag :a, :attributes => {:href => '/time_entries'}
end
end
end
context "#add" do
context "by admin user" do
setup do

View File

@ -57,7 +57,7 @@ class RepositoriesSubversionControllerTest < ActionController::TestCase
assert_response :success
assert_template 'show'
assert_not_nil assigns(:entries)
assert_equal ['folder', '.project', 'helloworld.c', 'textfile.txt'], assigns(:entries).collect(&:name)
assert_equal ['[folder_with_brackets]', 'folder', '.project', 'helloworld.c', 'textfile.txt'], assigns(:entries).collect(&:name)
entry = assigns(:entries).detect {|e| e.name == 'helloworld.c'}
assert_equal 'file', entry.kind
assert_equal 'subversion_test/helloworld.c', entry.path

View File

@ -133,6 +133,12 @@ class SearchControllerTest < ActionController::TestCase
assert_response :success
assert_template 'index'
end
def test_large_integer
get :index, :q => '4615713488'
assert_response :success
assert_template 'index'
end
def test_tokens_with_quotes
get :index, :id => 1, :q => '"good bye" hello "bye bye"'

View File

@ -116,9 +116,27 @@ class TimelogControllerTest < ActionController::TestCase
@request.session[:user_id] = 2
post :destroy, :id => 1
assert_redirected_to :action => 'details', :project_id => 'ecookbook'
assert_equal I18n.t(:notice_successful_delete), flash[:notice]
assert_nil TimeEntry.find_by_id(1)
end
def test_destroy_should_fail
# simulate that this fails (e.g. due to a plugin), see #5700
TimeEntry.class_eval do
before_destroy :stop_callback_chain
def stop_callback_chain ; return false ; end
end
@request.session[:user_id] = 2
post :destroy, :id => 1
assert_redirected_to :action => 'details', :project_id => 'ecookbook'
assert_equal I18n.t(:notice_unable_delete_time_entry), flash[:error]
assert_not_nil TimeEntry.find_by_id(1)
# remove the simulation
TimeEntry.before_destroy.reject! {|callback| callback.method == :stop_callback_chain }
end
def test_report_no_criteria
get :report, :project_id => 1
assert_response :success

View File

@ -61,6 +61,16 @@ class ActiveSupport::TestCase
def uploaded_test_file(name, mime)
ActionController::TestUploadedFile.new(ActiveSupport::TestCase.fixture_path + "/files/#{name}", mime)
end
# Mock out a file
def mock_file
file = 'a_file.png'
file.stubs(:size).returns(32)
file.stubs(:original_filename).returns('a_file.png')
file.stubs(:content_type).returns('image/png')
file.stubs(:read).returns(false)
file
end
# Use a temporary directory for attachment related tests
def set_tmp_attachments_directory

View File

@ -63,4 +63,23 @@ class AttachmentTest < ActiveSupport::TestCase
assert_equal 'f8139524ebb8f32e51976982cd20a85d', Attachment.disk_filename("test_accentué")[13..-1]
assert_equal 'cbb5b0f30978ba03731d61f9f6d10011', Attachment.disk_filename("test_accentué.ça")[13..-1]
end
context "Attachmnet#attach_files" do
should "add unsaved files to the object as unsaved attachments" do
# Max size of 0 to force Attachment creation failures
with_settings(:attachment_max_size => 0) do
@project = Project.generate!
response = Attachment.attach_files(@project, {
'1' => {'file' => mock_file, 'description' => 'test'},
'2' => {'file' => mock_file, 'description' => 'test'}
})
assert response[:unsaved].present?
assert_equal 2, response[:unsaved].length
assert response[:unsaved].first.new_record?
assert response[:unsaved].second.new_record?
assert_equal response[:unsaved], @project.unsaved_attachments
end
end
end
end

View File

@ -420,6 +420,10 @@ h2. Subtitle with %{color:red}red text%
h1. Another title
h2. An "Internet link":http://www.redmine.org/ inside subtitle
h2. "Project Name !/attachments/1234/logo_small.gif! !/attachments/5678/logo_2.png!":/projects/projectname/issues
RAW
expected = '<ul class="toc">' +
@ -428,8 +432,10 @@ RAW
'<li class="heading2"><a href="#Subtitle-with-another-Wiki-link">Subtitle with another Wiki link</a></li>' +
'<li class="heading2"><a href="#Subtitle-with-red-text">Subtitle with red text</a></li>' +
'<li class="heading1"><a href="#Another-title">Another title</a></li>' +
'<li class="heading2"><a href="#An-Internet-link-inside-subtitle">An Internet link inside subtitle</a></li>' +
'<li class="heading2"><a href="#Project-Name">Project Name</a></li>' +
'</ul>'
assert textilizable(raw).gsub("\n", "").include?(expected)
end

View File

@ -169,6 +169,15 @@ class MailHandlerTest < ActiveSupport::TestCase
assert issue.author.anonymous?
end
end
def test_add_issue_by_anonymous_user_with_no_from_address
Role.anonymous.add_permission!(:add_issues)
assert_no_difference 'User.count' do
issue = submit_email('ticket_by_empty_user.eml', :issue => {:project => 'ecookbook'}, :unknown_user => 'accept')
assert issue.is_a?(Issue)
assert issue.author.anonymous?
end
end
def test_add_issue_by_anonymous_user_on_private_project
Role.anonymous.add_permission!(:add_issues)
@ -340,6 +349,12 @@ class MailHandlerTest < ActiveSupport::TestCase
end
end
end
def test_email_with_long_subject_line
issue = submit_email('ticket_with_long_subject.eml')
assert issue.is_a?(Issue)
assert_equal issue.subject, 'New ticket on a given project with a very long subject line which exceeds 255 chars and should not be ignored but chopped off. And if the subject line is still not long enough, we just add more text. And more text. Wow, this is really annoying. Especially, if you have nothing to say...'[0,255]
end
private

View File

@ -18,7 +18,7 @@
require File.dirname(__FILE__) + '/../test_helper'
class RepositorySubversionTest < ActiveSupport::TestCase
fixtures :projects
fixtures :projects, :repositories
def setup
@project = Project.find(1)
@ -30,8 +30,8 @@ class RepositorySubversionTest < ActiveSupport::TestCase
@repository.fetch_changesets
@repository.reload
assert_equal 10, @repository.changesets.count
assert_equal 18, @repository.changes.count
assert_equal 11, @repository.changesets.count
assert_equal 20, @repository.changes.count
assert_equal 'Initial import.', @repository.changesets.find_by_revision('1').comments
end
@ -43,7 +43,7 @@ class RepositorySubversionTest < ActiveSupport::TestCase
assert_equal 5, @repository.changesets.count
@repository.fetch_changesets
assert_equal 10, @repository.changesets.count
assert_equal 11, @repository.changesets.count
end
def test_latest_changesets
@ -62,6 +62,32 @@ class RepositorySubversionTest < ActiveSupport::TestCase
changesets = @repository.latest_changesets('subversion_test/folder', 8)
assert_equal ["7", "6", "5", "2"], changesets.collect(&:revision)
end
def test_directory_listing_with_square_brackets_in_path
@repository.fetch_changesets
@repository.reload
entries = @repository.entries('subversion_test/[folder_with_brackets]')
assert_not_nil entries, 'Expect to find entries in folder_with_brackets'
assert_equal 1, entries.size, 'Expect one entry in folder_with_brackets'
assert_equal 'README.txt', entries.first.name
end
def test_directory_listing_with_square_brackets_in_base
@project = Project.find(1)
@repository = Repository::Subversion.create(:project => @project, :url => "file:///#{self.class.repository_path('subversion')}/subversion_test/[folder_with_brackets]")
@repository.fetch_changesets
@repository.reload
assert_equal 1, @repository.changesets.count, 'Expected to see 1 revision'
assert_equal 2, @repository.changes.count, 'Expected to see 2 changes, dir add and file add'
entries = @repository.entries('')
assert_not_nil entries, 'Expect to find entries'
assert_equal 1, entries.size, 'Expect a single entry'
assert_equal 'README.txt', entries.first.name
end
else
puts "Subversion test repository NOT FOUND. Skipping unit tests !!!"
def test_fake; assert true end

View File

@ -55,6 +55,21 @@ class UserTest < ActiveSupport::TestCase
assert user.save
end
context "User.login" do
should "be case-insensitive." do
u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
u.login = 'newuser'
u.password, u.password_confirmation = "password", "password"
assert u.save
u = User.new(:firstname => "Similar", :lastname => "User", :mail => "similaruser@somenet.foo")
u.login = 'NewUser'
u.password, u.password_confirmation = "password", "password"
assert !u.save
assert_equal I18n.translate('activerecord.errors.messages.taken'), u.errors.on(:login)
end
end
def test_mail_uniqueness_should_not_be_case_sensitive
u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
u.login = 'newuser1'
@ -88,6 +103,25 @@ class UserTest < ActiveSupport::TestCase
assert_equal 1, @admin.errors.count
end
context "User#try_to_login" do
should "fall-back to case-insensitive if user login is not found as-typed." do
user = User.try_to_login("AdMin", "admin")
assert_kind_of User, user
assert_equal "admin", user.login
end
should "select the exact matching user first" do
case_sensitive_user = User.generate_with_protected!(:login => 'changed', :password => 'admin', :password_confirmation => 'admin')
# bypass validations to make it appear like existing data
case_sensitive_user.update_attribute(:login, 'ADMIN')
user = User.try_to_login("ADMIN", "admin")
assert_kind_of User, user
assert_equal "ADMIN", user.login
end
end
def test_password
user = User.try_to_login("admin", "admin")
assert_kind_of User, user

View File

@ -57,7 +57,8 @@ module Redmine
# Returns an array of watchers' email addresses
def watcher_recipients
notified = watchers.collect(&:user).select(&:active?)
notified = watcher_users.active
if respond_to?(:visible?)
notified.reject! {|user| !visible?(user)}
end