+<% end %>
diff --git a/app/components/filter/filter_component.rb b/app/components/filter/filter_component.rb
new file mode 100644
index 000000000000..ea313e4d1975
--- /dev/null
+++ b/app/components/filter/filter_component.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+# -- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2010-2023 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+# ++
+module Filter
+ # rubocop:disable OpenProject/AddPreviewForViewComponent
+ class FilterComponent < ApplicationComponent
+ # rubocop:enable OpenProject/AddPreviewForViewComponent
+ options :query
+ options always_visible: false
+
+ def show_filters_section?
+ always_visible || params[:filters].present?
+ end
+
+ # Returns filters, active and inactive.
+ # In case a filter is active, the active one will be preferred over the inactive one.
+ def each_filter
+ allowed_filters.each do |filter|
+ active_filter = query.find_active_filter(filter.name)
+ additional_attributes = additional_filter_attributes(filter)
+
+ yield active_filter.presence || filter, active_filter.present?, additional_attributes
+ end
+ end
+
+ def allowed_filters
+ query
+ .available_filters
+ end
+
+ protected
+
+ # With this method we can pass additional options for each type of filter into the frontend. This is especially
+ # useful when we want to pass options for the autocompleter components.
+ #
+ # When the method is overwritten in a subclass, the subclass should call super(filter) to get the default attributes.
+ #
+ # @param filter [QueryFilter] the filter for which we want to pass additional attributes
+ # @return [Hash] the additional attributes for the filter, that will be yielded in the each_filter method
+ def additional_filter_attributes(filter)
+ case filter
+ when Queries::Filters::Shared::ProjectFilter
+ {
+ autocomplete_options: {
+ component: "opce-project-autocompleter",
+ resource: "projects",
+ filters: [
+ { name: "active", operator: "=", values: ["t"] }
+ ]
+ }
+ }
+ else
+ {}
+ end
+ end
+ end
+end
diff --git a/app/components/filters_component.sass b/app/components/filter/filters_component.sass
similarity index 88%
rename from app/components/filters_component.sass
rename to app/components/filter/filters_component.sass
index b2d7bf64a8b0..6e7856e6301f 100644
--- a/app/components/filters_component.sass
+++ b/app/components/filter/filters_component.sass
@@ -43,10 +43,5 @@
.advanced-filters--controls
margin-top: 1rem
- &-header
- display: flex
- justify-content: space-between
- margin-bottom: 1rem
-
- &-actions
- display: flex
\ No newline at end of file
+ &_top-margin
+ margin-top: 1rem
diff --git a/app/components/filters_component.html.erb b/app/components/filters_component.html.erb
deleted file mode 100644
index 58b2547b1357..000000000000
--- a/app/components/filters_component.html.erb
+++ /dev/null
@@ -1,153 +0,0 @@
-
diff --git a/app/components/filters_component.rb b/app/components/filters_component.rb
deleted file mode 100644
index c4e4404cb8a2..000000000000
--- a/app/components/filters_component.rb
+++ /dev/null
@@ -1,90 +0,0 @@
-# frozen_string_literal: true
-
-# -- copyright
-# OpenProject is an open source project management software.
-# Copyright (C) 2010-2023 the OpenProject GmbH
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License version 3.
-#
-# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-# Copyright (C) 2010-2013 the ChiliProject Team
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# See COPYRIGHT and LICENSE files for more details.
-# ++
-
-class FiltersComponent < ApplicationComponent
- options :query
- options :disabled
- options output_format: "params"
-
- renders_many :buttons, lambda { |**system_arguments|
- system_arguments[:ml] ||= 2
- Primer::Beta::Button.new(**system_arguments)
- }
-
- def show_filters_section?
- params[:filters].present? && !params.key?(:hide_filters_section)
- end
-
- # Returns filters, active and inactive.
- # In case a filter is active, the active one will be preferred over the inactive one.
- def each_filter
- allowed_filters.each do |filter|
- active_filter = query.find_active_filter(filter.name)
- additional_attributes = additional_filter_attributes(filter)
-
- yield active_filter.presence || filter, active_filter.present?, additional_attributes
- end
- end
-
- def allowed_filters
- query
- .available_filters
- end
-
- def filters_count
- @filters_count ||= query.filters.count
- end
-
- protected
-
- # With this method we can pass additional options for each type of filter into the frontend. This is especially
- # useful when we want to pass options for the autocompleter components.
- #
- # When the method is overwritten in a subclass, the subclass should call super(filter) to get the default attributes.
- #
- # @param filter [QueryFilter] the filter for which we want to pass additional attributes
- # @return [Hash] the additional attributes for the filter, that will be yielded in the each_filter method
- def additional_filter_attributes(filter)
- case filter
- when Queries::Filters::Shared::ProjectFilter
- {
- autocomplete_options: {
- component: "opce-project-autocompleter",
- resource: "projects",
- filters: [
- { name: "active", operator: "=", values: ["t"] }
- ]
- }
- }
- else
- {}
- end
- end
-end
diff --git a/app/components/members/index_page_header_component.html.erb b/app/components/members/index_page_header_component.html.erb
index d8742fbaff84..f86519661c10 100644
--- a/app/components/members/index_page_header_component.html.erb
+++ b/app/components/members/index_page_header_component.html.erb
@@ -2,26 +2,5 @@
render(Primer::OpenProject::PageHeader.new) do |header|
header.with_title { page_title }
header.with_breadcrumbs(breadcrumb_items, selected_item_font_weight: current_breadcrumb_element == page_title ? :bold : :normal)
-
- header.with_action_button(scheme: :primary,
- mobile_icon: :plus,
- mobile_label: t('activerecord.models.member'),
- size: :medium,
- aria: { label: I18n.t(:button_add_member) },
- title: I18n.t(:button_add_member),
- id: "add-member-button",
- data: add_button_data_attributes) do |button|
- button.with_leading_visual_icon(icon: :plus)
- t('activerecord.models.member')
- end
-
- header.with_action_icon_button(mobile_icon: "filter",
- scheme: :default,
- icon: "filter",
- label: I18n.t(:description_filter),
- id: "filter-member-button",
- aria: { label: I18n.t(:description_filter) },
- class: "toggle-member-filter-link",
- data: filter_button_data_attributes)
end
%>
diff --git a/app/components/members/index_page_header_component.rb b/app/components/members/index_page_header_component.rb
index 6c6df07280c1..907a6cc2f4e3 100644
--- a/app/components/members/index_page_header_component.rb
+++ b/app/components/members/index_page_header_component.rb
@@ -38,25 +38,6 @@ def initialize(project: nil)
@project = project
end
- def add_button_data_attributes
- attributes = {
- "members-form-target": "addMemberButton",
- action: "members-form#showAddMemberForm",
- "test-selector": "member-add-button"
- }
-
- attributes["trigger-initially"] = "true" if params[:show_add_members]
-
- attributes
- end
-
- def filter_button_data_attributes
- {
- "members-form-target": "filterMemberButton",
- action: "members-form#toggleMemberFilter"
- }
- end
-
def breadcrumb_items
[{ href: project_overview_path(@project.id), text: @project.name },
{ href: project_members_path(@project), text: t(:label_member_plural) },
diff --git a/app/components/members/index_sub_header_component.html.erb b/app/components/members/index_sub_header_component.html.erb
new file mode 100644
index 000000000000..d982cdf7950a
--- /dev/null
+++ b/app/components/members/index_sub_header_component.html.erb
@@ -0,0 +1,22 @@
+<%= render(Primer::OpenProject::SubHeader.new) do |subheader|
+ subheader.with_filter_button(label: I18n.t(:description_filter),
+ id: "filter-member-button",
+ aria: { label: I18n.t(:description_filter) },
+ class: "toggle-member-filter-link",
+ data: filter_button_data_attributes) do
+ I18n.t(:description_filter)
+ end
+
+ subheader.with_action_button(scheme: :primary,
+ aria: { label: I18n.t(:button_add_member) },
+ title: I18n.t(:button_add_member),
+ id: "add-member-button",
+ data: add_button_data_attributes) do |button|
+ button.with_leading_visual_icon(icon: :plus)
+ t('activerecord.models.member')
+ end
+
+ subheader.with_bottom_pane_component do
+ render ::Members::UserFilterComponent.new(params, **@members_filter_options)
+ end
+end %>
diff --git a/app/components/members/index_sub_header_component.rb b/app/components/members/index_sub_header_component.rb
new file mode 100644
index 000000000000..1ee814e243fb
--- /dev/null
+++ b/app/components/members/index_sub_header_component.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+# -- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2010-2024 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+# ++
+
+module Members
+ # rubocop:disable OpenProject/AddPreviewForViewComponent
+ class IndexSubHeaderComponent < ApplicationComponent
+ # rubocop:enable OpenProject/AddPreviewForViewComponent
+ include ApplicationHelper
+
+ def initialize(project: nil, filter_options: nil)
+ super
+ @project = project
+ @members_filter_options = filter_options
+ end
+
+ def add_button_data_attributes
+ attributes = {
+ "members-form-target": "addMemberButton",
+ action: "members-form#showAddMemberForm",
+ "test-selector": "member-add-button"
+ }
+
+ attributes["trigger-initially"] = "true" if params[:show_add_members]
+
+ attributes
+ end
+
+ def filter_button_data_attributes
+ {
+ "members-form-target": "filterMemberButton",
+ action: "members-form#toggleMemberFilter"
+ }
+ end
+ end
+end
diff --git a/app/components/projects/index_sub_header_component.html.erb b/app/components/projects/index_sub_header_component.html.erb
new file mode 100644
index 000000000000..bd09217edd2c
--- /dev/null
+++ b/app/components/projects/index_sub_header_component.html.erb
@@ -0,0 +1,23 @@
+<%= render(Primer::OpenProject::SubHeader.new(data: {
+ controller: "filters",
+ "application-target": "dynamic",
+ })) do |subheader|
+ subheader.with_filter_component do
+ render(Filter::FilterButtonComponent.new(query: @query, disabled: @disable_buttons))
+ end
+
+ subheader.with_action_button(tag: :a,
+ href: new_project_path,
+ scheme: :primary,
+ disabled: @disable_buttons,
+ size: :medium,
+ aria: { label: I18n.t(:label_project_new) },
+ data: { 'test-selector': 'project-new-button' }) do |button|
+ button.with_leading_visual_icon(icon: :plus)
+ Project.model_name.human
+ end if @current_user.allowed_globally?(:add_project)
+
+ subheader.with_bottom_pane_component(mt: 0) do
+ render(Projects::ProjectsFiltersComponent.new(query: @query))
+ end
+ end %>
diff --git a/app/components/projects/index_sub_header_component.rb b/app/components/projects/index_sub_header_component.rb
new file mode 100644
index 000000000000..cbd16be7fa47
--- /dev/null
+++ b/app/components/projects/index_sub_header_component.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+# -- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2010-2024 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+# ++
+
+module Projects
+ # rubocop:disable OpenProject/AddPreviewForViewComponent
+ class IndexSubHeaderComponent < ApplicationComponent
+ # rubocop:enable OpenProject/AddPreviewForViewComponent
+ include ApplicationHelper
+
+ def initialize(query:, current_user:, disable_buttons: nil)
+ super
+ @query = query
+ @current_user = current_user
+ @disable_buttons = disable_buttons
+ end
+ end
+end
diff --git a/app/components/projects/projects_filters_component.rb b/app/components/projects/projects_filters_component.rb
index 450e2545aa77..e467c186dd1f 100644
--- a/app/components/projects/projects_filters_component.rb
+++ b/app/components/projects/projects_filters_component.rb
@@ -28,7 +28,9 @@
# See COPYRIGHT and LICENSE files for more details.
# ++
-class Projects::ProjectsFiltersComponent < FiltersComponent
+# rubocop:disable OpenProject/AddPreviewForViewComponent
+class Projects::ProjectsFiltersComponent < Filter::FilterComponent
+ # rubocop:enable OpenProject/AddPreviewForViewComponent
def allowed_filters
super
.select { |f| allowed_filter?(f) }
diff --git a/app/components/projects/row_component.rb b/app/components/projects/row_component.rb
index 34c5475e7a70..d3a8c9b6f32c 100644
--- a/app/components/projects/row_component.rb
+++ b/app/components/projects/row_component.rb
@@ -199,6 +199,8 @@ def additional_css_class(column)
"project--hierarchy #{project.archived? ? 'archived' : ''}"
elsif %i[status_explanation description].include?(column.attribute)
"project-long-text-container"
+ elsif column.attribute == :favored
+ "-w-abs-45"
elsif custom_field_column?(column)
cf = column.custom_field
formattable = cf.field_format == "text" ? " project-long-text-container" : ""
diff --git a/app/components/projects/settings/project_custom_field_sections/index_component.html.erb b/app/components/projects/settings/project_custom_field_sections/index_component.html.erb
index 5da79313acf2..3c31b3294e78 100644
--- a/app/components/projects/settings/project_custom_field_sections/index_component.html.erb
+++ b/app/components/projects/settings/project_custom_field_sections/index_component.html.erb
@@ -1,23 +1,23 @@
<%=
component_wrapper(data: wrapper_data_attributes) do
flex_layout do |flex|
- flex.with_row(mt: 3) do
- render(Primer::Alpha::TextField.new(
- name: "project-custom-fields-mapping-filter",
- label: t('projects.settings.project_custom_fields.filter.label'),
- visually_hide_label: true,
- placeholder: t('projects.settings.project_custom_fields.filter.label'),
- leading_visual: {
- icon: :search,
- size: :small
- },
- show_clear_button: true,
- clear_button_id: "project-custom-fields-mapping-filter-clear-button",
- data: {
- action: "input->projects--settings--project-custom-fields-mapping-filter#filterLists",
- "projects--settings--project-custom-fields-mapping-filter-target": "filter"
- }
- ))
+ flex.with_row do
+ render(Primer::OpenProject::SubHeader.new) do |subheader|
+ subheader.with_filter_input(name: "project-custom-fields-mapping-filter",
+ label: t('projects.settings.project_custom_fields.filter.label'),
+ visually_hide_label: true,
+ placeholder: t('projects.settings.project_custom_fields.filter.label'),
+ leading_visual: {
+ icon: :search,
+ size: :small
+ },
+ show_clear_button: true,
+ clear_button_id: "project-custom-fields-mapping-filter-clear-button",
+ data: {
+ action: "input->projects--settings--project-custom-fields-mapping-filter#filterLists",
+ "projects--settings--project-custom-fields-mapping-filter-target": "filter"
+ })
+ end
end
@project_custom_field_sections.each do |project_custom_field_section|
diff --git a/app/components/projects/settings/project_custom_field_sections/show_component.html.erb b/app/components/projects/settings/project_custom_field_sections/show_component.html.erb
index 33c01da2fde6..727d8901228b 100644
--- a/app/components/projects/settings/project_custom_field_sections/show_component.html.erb
+++ b/app/components/projects/settings/project_custom_field_sections/show_component.html.erb
@@ -1,6 +1,6 @@
<%=
component_wrapper do
- render(border_box_container(mt: 3, classes: 'op-project-custom-field-section', data: {
+ render(border_box_container(mb: 3, classes: 'op-project-custom-field-section', data: {
test_selector: "project-custom-field-section-#{@project_custom_field_section.id}"
})) do |component|
component.with_header(font_weight: :bold, py: 2) do
diff --git a/app/components/projects/table_component.html.erb b/app/components/projects/table_component.html.erb
index a9628a3a672e..9746443263a5 100644
--- a/app/components/projects/table_component.html.erb
+++ b/app/components/projects/table_component.html.erb
@@ -56,16 +56,22 @@ See COPYRIGHT and LICENSE files for more details.
<% elsif sortable_column?(column) %>
<%= build_sort_header column.attribute,
order_options(column) %>
+ <% elsif column.attribute == :favored %>
+
diff --git a/app/components/settings/project_custom_fields/header_component.html.erb b/app/components/settings/project_custom_fields/header_component.html.erb
index d256f4bbed2d..d05b23f37dd9 100644
--- a/app/components/settings/project_custom_fields/header_component.html.erb
+++ b/app/components/settings/project_custom_fields/header_component.html.erb
@@ -1,32 +1,36 @@
-<% button_block = lambda do |button|
- button.with_leading_visual_icon(icon: :plus)
- t('settings.project_attributes.label_new_section')
-end %>
-
-<%=
- component_wrapper do
+<%= component_wrapper do %>
+ <%=
render Primer::OpenProject::PageHeader.new do |header|
header.with_title(variant: :default) { t("settings.project_attributes.heading") }
header.with_description { t("settings.project_attributes.heading_description") }
header.with_breadcrumbs(breadcrumbs_items)
- header.with_action_button(tag: :a,
- href: new_admin_settings_project_custom_field_path(type: "ProjectCustomField"),
- scheme: :primary,
- data: { turbo: "false", test_selector: "new-project-custom-field-button" },
- mobile_icon: :plus,
- mobile_label: t("settings.project_attributes.label_new_attribute")) do |button|
+ end
+ %>
+
+ <%=
+ render Primer::OpenProject::SubHeader.new do |subheader|
+ subheader.with_action_component do
+ render(Primer::Alpha::Dialog.new(id: "project-custom-field-section-dialog", title: t('settings.project_attributes.label_new_section'), size: :medium_portrait)) do |dialog|
+ dialog.with_show_button('aria-label': t('settings.project_attributes.label_new_section')) do |button|
+ button.with_leading_visual_icon(icon: :plus)
+ t('settings.project_attributes.label_new_section')
+ end
+ dialog.with_body do
+ render(Settings::ProjectCustomFieldSections::DialogBodyFormComponent.new)
+ end
+ end
+ end
+
+ subheader.with_action_button(tag: :a,
+ href: new_admin_settings_project_custom_field_path(type: "ProjectCustomField"),
+ scheme: :primary,
+ data: { turbo: "false", test_selector: "new-project-custom-field-button" },
+ mobile_icon: :plus,
+ mobile_label: t("settings.project_attributes.label_new_attribute")) do |button|
button.with_leading_visual_icon(icon: :plus)
t("settings.project_attributes.label_new_attribute")
end
- header.with_action_dialog(mobile_icon: :plus,
- mobile_label: t('settings.project_attributes.label_new_section'),
- dialog_arguments: {id: "project-custom-field-section-dialog", title: t('settings.project_attributes.label_new_section', size: :medium_portrait), size: :medium_portrait},
- button_arguments: {'aria-label': t('settings.project_attributes.label_new_section'), button_block: button_block}) do |dialog|
- dialog.with_body do
- render(Settings::ProjectCustomFieldSections::DialogBodyFormComponent.new)
- end
- end
end
- end
-%>
+ %>
+<% end %>
diff --git a/app/components/settings/project_custom_fields/project_custom_field_mapping/new_project_mapping_component.html.erb b/app/components/settings/project_custom_fields/project_custom_field_mapping/new_project_mapping_component.html.erb
new file mode 100644
index 000000000000..817a44612ec6
--- /dev/null
+++ b/app/components/settings/project_custom_fields/project_custom_field_mapping/new_project_mapping_component.html.erb
@@ -0,0 +1,42 @@
+<%=
+ component_wrapper do
+ render(
+ Primer::Alpha::Dialog.new(
+ id: dialog_id,
+ title:,
+ test_selector: dialog_id,
+ size: :large
+ )
+ ) do |dialog|
+ dialog.with_show_button(scheme: :primary) do |button|
+ button.with_leading_visual_icon(icon: 'op-include-projects')
+ show_button_text
+ end
+
+ dialog.with_header(
+ show_divider: false,
+ visually_hide_title: false
+ )
+
+ primer_form_with(
+ class: "op-new-project-mapping-form",
+ model: @project_mapping,
+ url: link_admin_settings_project_custom_field_path(@project_custom_field),
+ data: { turbo: true },
+ method: :post
+ ) do |form|
+ concat(render(Primer::Alpha::Dialog::Body.new(
+ id: dialog_body_id, test_selector: dialog_body_id, aria: { label: title },
+ style: "min-height: 300px"
+ )) do
+ render(Projects::CustomFields::CustomFieldMappingForm.new(form, project_custom_field: @project_custom_field))
+ end)
+
+ concat(render(Primer::Alpha::Dialog::Footer.new(show_divider: false)) do
+ concat(render(Primer::ButtonComponent.new(data: { 'close-dialog-id': dialog_id })) { cancel_button_text })
+ concat(render(Primer::ButtonComponent.new(scheme: :primary, type: :submit)) { submit_button_text })
+ end)
+ end
+ end
+ end
+%>
diff --git a/app/components/settings/project_custom_fields/project_custom_field_mapping/new_project_mapping_component.rb b/app/components/settings/project_custom_fields/project_custom_field_mapping/new_project_mapping_component.rb
new file mode 100644
index 000000000000..b6b8e71b9bb8
--- /dev/null
+++ b/app/components/settings/project_custom_fields/project_custom_field_mapping/new_project_mapping_component.rb
@@ -0,0 +1,68 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2012-2023 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+module Settings
+ module ProjectCustomFields
+ module ProjectCustomFieldMapping
+ class NewProjectMappingComponent < ApplicationComponent # rubocop:disable OpenProject/AddPreviewForViewComponent
+ include OpTurbo::Streamable
+
+ options dialog_id: "settings--new-project-custom-field-mapping-component",
+ dialog_body_id: "settings--new-project-custom-field-mapping-body-component"
+
+ def initialize(project_mapping:, project_custom_field:, **)
+ @project_mapping = project_mapping
+ @project_custom_field = project_custom_field
+ super(@project_mapping, **)
+ end
+
+ def render?
+ !@project_custom_field.required?
+ end
+
+ private
+
+ def title
+ I18n.t("projects.settings.project_custom_fields.new_project_mapping_form.add_projects")
+ end
+
+ def show_button_text
+ I18n.t("projects.settings.project_custom_fields.new_project_mapping_form.add_projects")
+ end
+
+ def cancel_button_text
+ I18n.t("button_cancel")
+ end
+
+ def submit_button_text
+ I18n.t("button_add")
+ end
+ end
+ end
+ end
+end
diff --git a/app/components/settings/project_custom_fields/project_custom_field_mapping/new_project_mapping_component.sass b/app/components/settings/project_custom_fields/project_custom_field_mapping/new_project_mapping_component.sass
new file mode 100644
index 000000000000..76511b9c5b3e
--- /dev/null
+++ b/app/components/settings/project_custom_fields/project_custom_field_mapping/new_project_mapping_component.sass
@@ -0,0 +1,8 @@
+@import 'helpers'
+
+.op-new-project-mapping-form
+ .ng-placeholder
+ @extend .icon-search
+ &:before
+ @include icon-font-common
+ margin-right: 10px
diff --git a/app/components/settings/project_custom_fields/project_custom_field_mapping/row_component.html.erb b/app/components/settings/project_custom_fields/project_custom_field_mapping/row_component.html.erb
index 097b38764a0a..c92f886b908c 100644
--- a/app/components/settings/project_custom_fields/project_custom_field_mapping/row_component.html.erb
+++ b/app/components/settings/project_custom_fields/project_custom_field_mapping/row_component.html.erb
@@ -27,7 +27,14 @@ See COPYRIGHT and LICENSE files for more details.
++#%>
-<%= component_wrapper(tag: "tr", class: row_css_class, data: { turbo: true }) do %>
+<%
+ wrapper_data_attributes = {
+ turbo: true,
+ "projects--settings--available-project-mappings-filter-target": "searchItem"
+ }
+%>
+
+<%= component_wrapper(tag: "tr", class: row_css_class, data: wrapper_data_attributes) do %>
<% columns.each do |column| %>
<%= column_value(column) %>
diff --git a/app/components/statuses/row_component.rb b/app/components/statuses/row_component.rb
index 8c2f1d8d6b6c..0533192cbb81 100644
--- a/app/components/statuses/row_component.rb
+++ b/app/components/statuses/row_component.rb
@@ -50,6 +50,10 @@ def readonly?
checkmark(status.is_readonly?)
end
+ def excluded_from_totals?
+ checkmark(status.excluded_from_totals?)
+ end
+
def color
helpers.icon_for_color status.color
end
diff --git a/app/components/statuses/table_component.rb b/app/components/statuses/table_component.rb
index b0c5dbadf554..240cf1490e55 100644
--- a/app/components/statuses/table_component.rb
+++ b/app/components/statuses/table_component.rb
@@ -60,9 +60,10 @@ def headers
[:name, { caption: Status.human_attribute_name(:name) }],
[:color, { caption: Status.human_attribute_name(:color) }],
[:done_ratio, { caption: WorkPackage.human_attribute_name(:done_ratio) }],
- [:default?, { caption: Status.human_attribute_name(:is_default) }],
- [:closed?, { caption: Status.human_attribute_name(:is_closed) }],
- [:readonly?, { caption: Status.human_attribute_name(:is_readonly) }],
+ [:default?, { caption: I18n.t("statuses.index.headers.is_default") }],
+ [:closed?, { caption: I18n.t("statuses.index.headers.is_closed") }],
+ [:readonly?, { caption: I18n.t("statuses.index.headers.is_readonly") }],
+ [:excluded_from_totals?, { caption: I18n.t("statuses.index.headers.excluded_from_totals") }],
[:sort, { caption: I18n.t(:label_sort) }]
]
end
diff --git a/app/components/work_packages/share/share_counter_component.html.erb b/app/components/work_packages/share/share_counter_component.html.erb
index 3b5b5c6f2ce4..855f37330382 100644
--- a/app/components/work_packages/share/share_counter_component.html.erb
+++ b/app/components/work_packages/share/share_counter_component.html.erb
@@ -1,5 +1,3 @@
<%
- concat(render(Primer::Beta::Octicon.new(icon: 'person')))
-
- concat(render(Primer::Beta::Text.new(ml: 2)) { I18n.t('work_package.sharing.count', count:) })
+ concat(render(Primer::Beta::Text.new) { I18n.t('work_package.sharing.count', count:) })
%>
diff --git a/app/contracts/settings/working_days_and_hours_params_contract.rb b/app/contracts/settings/working_days_and_hours_params_contract.rb
new file mode 100644
index 000000000000..c6dbd9864c48
--- /dev/null
+++ b/app/contracts/settings/working_days_and_hours_params_contract.rb
@@ -0,0 +1,119 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2012-2024 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+module Settings
+ class WorkingDaysAndHoursParamsContract < ::ParamsContract
+ include RequiresAdminGuard
+
+ validate :working_days_are_present
+ validate :hours_per_day_are_present
+ validate :days_per_week_are_present
+ validate :days_per_month_are_present
+ validate :durations_are_positive_values
+ validate :durations_are_within_bounds
+ validate :days_per_week_and_days_per_month_are_consistent
+ validate :unique_job
+
+ protected
+
+ def working_days_are_present
+ if working_days.blank?
+ errors.add :base, :working_days_are_missing
+ end
+ end
+
+ def hours_per_day_are_present
+ if hours_per_day.blank?
+ errors.add :base, :hours_per_day_are_missing
+ end
+ end
+
+ def days_per_week_are_present
+ if days_per_week.blank?
+ errors.add :base, :days_per_week_are_missing
+ end
+ end
+
+ def days_per_month_are_present
+ if days_per_month.blank?
+ errors.add :base, :days_per_month_are_missing
+ end
+ end
+
+ def durations_are_positive_values
+ if hours_per_day &&
+ days_per_week &&
+ days_per_month &&
+ any_duration_is_negative_or_zero?
+ errors.add :base, :durations_are_not_positive_numbers
+ end
+ end
+
+ def durations_are_within_bounds
+ errors.add :base, :hours_per_day_is_out_of_bounds if hours_per_day.to_i > 24
+ errors.add :base, :days_per_week_is_out_of_bounds if days_per_week.to_i > 7
+ errors.add :base, :days_per_month_is_out_of_bounds if days_per_month.to_i > 31
+ end
+
+ def any_duration_is_negative_or_zero?
+ !hours_per_day.to_i.positive? ||
+ !days_per_week.to_i.positive? ||
+ !days_per_month.to_i.positive?
+ end
+
+ def days_per_week_and_days_per_month_are_consistent
+ if days_per_week &&
+ days_per_month &&
+ days_per_week.to_i != days_per_month.to_i / ChronicDuration::FULL_WEEKS_PER_MONTH
+ errors.add :base, :days_per_week_and_days_per_month_are_inconsistent
+ end
+ end
+
+ def unique_job
+ WorkPackages::ApplyWorkingDaysChangeJob.new.check_concurrency do
+ errors.add :base, :previous_working_day_changes_unprocessed
+ end
+ end
+
+ def working_days
+ params[:working_days]
+ end
+
+ def hours_per_day
+ params[:hours_per_day]
+ end
+
+ def days_per_week
+ params[:days_per_week]
+ end
+
+ def days_per_month
+ params[:days_per_month]
+ end
+ end
+end
diff --git a/app/controllers/admin/settings/project_custom_fields_controller.rb b/app/controllers/admin/settings/project_custom_fields_controller.rb
index 82271cbc4901..8844d1b4f72c 100644
--- a/app/controllers/admin/settings/project_custom_fields_controller.rb
+++ b/app/controllers/admin/settings/project_custom_fields_controller.rb
@@ -39,10 +39,11 @@ class ProjectCustomFieldsController < ::Admin::SettingsController
# rubocop:disable Rails/LexicallyScopedActionFilter
before_action :set_sections, only: %i[show index edit update move drop]
before_action :find_custom_field,
- only: %i(show edit project_mappings unlink update destroy delete_option reorder_alphabetical move drop)
+ only: %i(show edit project_mappings link unlink update destroy delete_option reorder_alphabetical move drop)
before_action :prepare_custom_option_position, only: %i(update create)
before_action :find_custom_option, only: :delete_option
before_action :project_custom_field_mappings_query, only: %i[project_mappings unlink]
+ before_action :find_link_project_custom_field_mapping, only: :link
before_action :find_unlink_project_custom_field_mapping, only: :unlink
# rubocop:enable Rails/LexicallyScopedActionFilter
@@ -68,14 +69,34 @@ def new
def edit; end
- def project_mappings; end
+ def project_mappings
+ @project_mapping = ProjectCustomFieldProjectMapping.new(project_custom_field: @custom_field)
+ end
+
+ def link
+ create_service = ProjectCustomFieldProjectMappings::BulkCreateService
+ .new(user: current_user, project: @project, project_custom_field: @custom_field,
+ include_sub_projects: include_sub_projects?)
+ .call
+
+ create_service.on_success { render_project_list }
+
+ create_service.on_failure do
+ update_flash_message_via_turbo_stream(
+ message: join_flash_messages(create_service.errors.full_messages),
+ full: true, dismiss_scheme: :hide, scheme: :danger
+ )
+ end
+
+ respond_to_with_turbo_streams(status: create_service.success? ? :ok : :unprocessable_entity)
+ end
def unlink
delete_service = ProjectCustomFieldProjectMappings::DeleteService
.new(user: current_user, model: @project_custom_field_mapping)
.call
- delete_service.on_success { render_unlink_response }
+ delete_service.on_success { render_project_list }
delete_service.on_failure do
update_flash_message_via_turbo_stream(
@@ -126,13 +147,18 @@ def destroy
private
- def render_unlink_response
+ def render_project_list
+ update_via_turbo_stream(
+ component: Settings::ProjectCustomFields::ProjectCustomFieldMapping::NewProjectMappingComponent.new(
+ project_mapping: ProjectCustomFieldProjectMapping.new(project_custom_field: @custom_field),
+ project_custom_field: @custom_field
+ )
+ )
update_via_turbo_stream(
component: Settings::ProjectCustomFields::ProjectCustomFieldMapping::TableComponent.new(
- query: @project_custom_field_mappings_query,
+ query: project_custom_field_mappings_query,
params: { custom_field: @custom_field }
- ),
- status: :ok
+ )
)
end
@@ -169,6 +195,17 @@ def find_unlink_project_custom_field_mapping
respond_with_turbo_streams
end
+ def find_link_project_custom_field_mapping
+ @project = Project.find(permitted_params.project_custom_field_project_mapping[:project_id])
+ rescue ActiveRecord::RecordNotFound
+ update_flash_message_via_turbo_stream(
+ message: t(:notice_file_not_found), full: true, dismiss_scheme: :hide, scheme: :danger
+ )
+ render_project_list
+
+ respond_with_turbo_streams
+ end
+
def find_custom_field
@custom_field = ProjectCustomField.find(params[:id])
rescue ActiveRecord::RecordNotFound
@@ -181,5 +218,9 @@ def drop_success_streams(call)
update_section_via_turbo_stream(project_custom_field_section: call.result[:old_section])
end
end
+
+ def include_sub_projects?
+ ActiveRecord::Type::Boolean.new.cast(permitted_params.project_custom_field_project_mapping[:include_sub_projects])
+ end
end
end
diff --git a/app/controllers/admin/settings/working_days_settings_controller.rb b/app/controllers/admin/settings/working_days_and_hours_settings_controller.rb
similarity index 85%
rename from app/controllers/admin/settings/working_days_settings_controller.rb
rename to app/controllers/admin/settings/working_days_and_hours_settings_controller.rb
index fa0d390f7e49..b0bd50d11abd 100644
--- a/app/controllers/admin/settings/working_days_settings_controller.rb
+++ b/app/controllers/admin/settings/working_days_and_hours_settings_controller.rb
@@ -27,11 +27,11 @@
#++
module Admin::Settings
- class WorkingDaysSettingsController < ::Admin::SettingsController
- menu_item :working_days
+ class WorkingDaysAndHoursSettingsController < ::Admin::SettingsController
+ menu_item :working_days_and_hours
def default_breadcrumb
- t(:label_working_days)
+ t(:label_working_days_and_hours)
end
def failure_callback(call)
@@ -43,14 +43,14 @@ def failure_callback(call)
protected
def settings_params
- settings = super
- settings[:working_days] = working_days_params(settings)
- settings[:non_working_days] = non_working_days_params
- settings
+ super.tap do |settings|
+ settings[:working_days] = working_days_params(settings)
+ settings[:non_working_days] = non_working_days_params
+ end
end
def update_service
- ::Settings::WorkingDaysUpdateService
+ ::Settings::WorkingDaysAndHoursUpdateService
end
private
diff --git a/app/controllers/statuses_controller.rb b/app/controllers/statuses_controller.rb
index 74bd847206b0..c3b0e10784f1 100644
--- a/app/controllers/statuses_controller.rb
+++ b/app/controllers/statuses_controller.rb
@@ -61,7 +61,7 @@ def create
def update
@status = Status.find(params[:id])
if @status.update(permitted_params.status)
- apply_status_p_complete_change
+ recompute_progress_values
flash[:notice] = I18n.t(:notice_successful_update)
redirect_to action: "index"
else
@@ -97,14 +97,16 @@ def show_local_breadcrumb
true
end
- def apply_status_p_complete_change
- return unless WorkPackage.use_status_for_done_ratio?
- return unless @status.default_done_ratio_previously_changed?
+ def recompute_progress_values
+ attributes_triggering_recomputing = ["excluded_from_totals"]
+ attributes_triggering_recomputing << "default_done_ratio" if WorkPackage.use_status_for_done_ratio?
+ changes = @status.previous_changes.slice(*attributes_triggering_recomputing)
+ return if changes.empty?
- WorkPackages::Progress::ApplyStatusesPCompleteJob
- .perform_later(cause_type: "status_p_complete_changed",
+ WorkPackages::Progress::ApplyStatusesChangeJob
+ .perform_later(cause_type: "status_changed",
status_name: @status.name,
status_id: @status.id,
- change: @status.default_done_ratio_previous_change)
+ changes:)
end
end
diff --git a/app/controllers/work_packages/progress_controller.rb b/app/controllers/work_packages/progress_controller.rb
index a1024129733d..d9e5cfa196a4 100644
--- a/app/controllers/work_packages/progress_controller.rb
+++ b/app/controllers/work_packages/progress_controller.rb
@@ -130,7 +130,17 @@ def extract_persisted_progress_attributes
def work_package_params
params.require(:work_package)
- .permit(allowed_params)
+ .permit(allowed_params).tap do |wp_params|
+ %w[estimated_hours remaining_hours].each do |attr|
+ if wp_params[attr].present?
+ begin
+ wp_params[attr] = DurationConverter.parse(wp_params[attr])
+ rescue ChronicDuration::DurationParseError
+ @work_package.errors.add(attr.to_sym, :invalid)
+ end
+ end
+ end
+ end
end
def allowed_params
@@ -141,12 +151,6 @@ def allowed_params
end
end
- def reject_params_that_dont_differ_from_persisted_values
- work_package_params.reject do |key, value|
- @persisted_progress_attributes[key.to_s].to_f.to_s == value.to_f.to_s
- end
- end
-
def filtered_work_package_params
{}.tap do |filtered_params|
filtered_params[:estimated_hours] = work_package_params["estimated_hours"] if estimated_hours_touched?
diff --git a/app/forms/projects/custom_fields/custom_field_mapping_form.rb b/app/forms/projects/custom_fields/custom_field_mapping_form.rb
new file mode 100644
index 000000000000..2d0501ee2c4d
--- /dev/null
+++ b/app/forms/projects/custom_fields/custom_field_mapping_form.rb
@@ -0,0 +1,69 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2012-2024 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+module Projects::CustomFields
+ class CustomFieldMappingForm < ApplicationForm
+ form do |f|
+ f.group(layout: :horizontal) do |f_group|
+ f_group.project_autocompleter(
+ name: :id,
+ label: Project.model_name.human,
+ visually_hide_label: true,
+ autocomplete_options: {
+ openDirectly: false,
+ focusDirectly: false,
+ dropdownPosition: "bottom",
+ disabledProjects: projects_with_custom_field_mapping,
+ inputName: "project_custom_field_project_mapping[project_id]"
+ }
+ )
+
+ f_group.check_box(
+ name: :include_sub_projects,
+ label: I18n.t("projects.settings.project_custom_fields.new_project_mapping_form.include_sub_projects"),
+ checked: false,
+ label_arguments: { class: "no-wrap" }
+ )
+ end
+ end
+
+ def initialize(project_custom_field:)
+ super()
+ @project_custom_field = project_custom_field
+ end
+
+ private
+
+ def projects_with_custom_field_mapping
+ ProjectCustomFieldProjectMapping
+ .where(project_custom_field: @project_custom_field)
+ .pluck(:project_id)
+ .to_h { |id| [id, id] }
+ end
+ end
+end
diff --git a/app/forms/work_packages/progress_form.rb b/app/forms/work_packages/progress_form.rb
index baf36ce3d0ea..0e662e9b177e 100644
--- a/app/forms/work_packages/progress_form.rb
+++ b/app/forms/work_packages/progress_form.rb
@@ -97,7 +97,7 @@ def initialize(work_package:,
def ensure_only_one_error_for_remaining_work_exceeding_work
if work_package.errors.added?(:remaining_hours, :cant_exceed_work) &&
- work_package.errors.added?(:estimated_hours, :cant_be_inferior_to_remaining_work)
+ work_package.errors.added?(:estimated_hours, :cant_be_inferior_to_remaining_work)
error_to_delete =
if @focused_field == :estimated_hours
:remaining_hours
@@ -154,10 +154,12 @@ def render_readonly_text_field(group,
def field_value(name)
errors = @work_package.errors.where(name)
- if user_value = errors.map { |error| error.options[:value] }.find { !_1.nil? }
+ if (user_value = errors.map { |error| error.options[:value] }.find { !_1.nil? })
user_value
- else
+ elsif name == :done_ratio
format_to_smallest_fractional_part(@work_package.public_send(name))
+ else
+ DurationConverter.output(@work_package.public_send(name))
end
end
diff --git a/app/models/exports/formatters/custom_field.rb b/app/models/exports/formatters/custom_field.rb
index 5815fb2a18ff..ef55bd0aff25 100644
--- a/app/models/exports/formatters/custom_field.rb
+++ b/app/models/exports/formatters/custom_field.rb
@@ -1,12 +1,12 @@
module Exports
module Formatters
class CustomField < Default
- def self.apply?(attribute, _export_format)
- attribute.start_with?("cf_")
+ def self.apply?(attribute, export_format)
+ export_format != :pdf && attribute.start_with?("cf_")
end
##
- # Takes a WorkPackage and an attribute and returns the value to be exported.
+ # Takes a WorkPackage or Project and an attribute and returns the value to be exported.
def retrieve_value(object)
custom_field = find_custom_field(object)
return "" if custom_field.nil?
diff --git a/app/models/exports/formatters/custom_field_pdf.rb b/app/models/exports/formatters/custom_field_pdf.rb
new file mode 100644
index 000000000000..a299f785a169
--- /dev/null
+++ b/app/models/exports/formatters/custom_field_pdf.rb
@@ -0,0 +1,27 @@
+module Exports
+ module Formatters
+ class CustomFieldPdf < CustomField
+ def self.apply?(attribute, export_format)
+ export_format == :pdf && attribute.start_with?("cf_")
+ end
+
+ ##
+ # Print the value meant for export.
+ #
+ # - For boolean values, use the Yes/No formatting for the PDF
+ # treat nil as false
+ # - For long text values, output the plain value
+ def format_for_export(object, custom_field)
+ case custom_field.field_format
+ when "bool"
+ value = object.typed_custom_value_for(custom_field)
+ value ? I18n.t(:general_text_Yes) : I18n.t(:general_text_No)
+ when "text"
+ object.typed_custom_value_for(custom_field)
+ else
+ object.formatted_custom_value_for(custom_field)
+ end
+ end
+ end
+ end
+end
diff --git a/app/models/journal.rb b/app/models/journal.rb
index fb5f3f329a38..1a9229a397a3 100644
--- a/app/models/journal.rb
+++ b/app/models/journal.rb
@@ -71,13 +71,13 @@ class Journal < ApplicationRecord
changed_days
status_name
status_id
- status_p_complete_change
+ status_changes
],
prefix: true
VALID_CAUSE_TYPES = %w[
default_attribute_written
progress_mode_changed_to_status_based
- status_p_complete_changed
+ status_changed
system_update
work_package_children_changed_times
work_package_parent_changed_times
diff --git a/app/models/journal/caused_by_status_p_complete_changed.rb b/app/models/journal/caused_by_status_changed.rb
similarity index 84%
rename from app/models/journal/caused_by_status_p_complete_changed.rb
rename to app/models/journal/caused_by_status_changed.rb
index da648aca57d6..4e28458fbc75 100644
--- a/app/models/journal/caused_by_status_p_complete_changed.rb
+++ b/app/models/journal/caused_by_status_changed.rb
@@ -26,14 +26,14 @@
# See COPYRIGHT and LICENSE files for more details.
#++
#
-class Journal::CausedByStatusPCompleteChanged < CauseOfChange::Base
- def initialize(status_name:, status_id:, status_p_complete_change:)
+class Journal::CausedByStatusChanged < CauseOfChange::Base
+ def initialize(status_name:, status_id:, status_changes:)
additional = {
"status_name" => status_name,
"status_id" => status_id,
- "status_p_complete_change" => status_p_complete_change
+ "status_changes" => status_changes
}
- super("status_p_complete_changed", additional)
+ super("status_changed", additional)
end
end
diff --git a/app/models/notifications/scopes/unsent_reminders_before.rb b/app/models/notifications/scopes/unsent_reminders_before.rb
index 7fb881482109..4434f0b5032a 100644
--- a/app/models/notifications/scopes/unsent_reminders_before.rb
+++ b/app/models/notifications/scopes/unsent_reminders_before.rb
@@ -36,8 +36,9 @@ module UnsentRemindersBefore
def unsent_reminders_before(recipient:, time:)
where(Notification.arel_table[:created_at].lteq(time))
.where(recipient:)
- .where("read_ian IS NULL OR read_ian IS FALSE")
+ .where(read_ian: [false, nil])
.where(mail_reminder_sent: false)
+ .where(mail_alert_sent: [false, nil])
end
end
end
diff --git a/app/models/permitted_params.rb b/app/models/permitted_params.rb
index 241c79b26db5..fd947aef170d 100644
--- a/app/models/permitted_params.rb
+++ b/app/models/permitted_params.rb
@@ -563,6 +563,7 @@ def self.permitted_attributes
project_id
custom_field_id
custom_field_section_id
+ include_sub_projects
),
query: %i(
name
@@ -593,6 +594,7 @@ def self.permitted_attributes
name
color_id
default_done_ratio
+ excluded_from_totals
is_closed
is_default
is_readonly
diff --git a/app/models/projects/exports/formatters/active.rb b/app/models/projects/exports/formatters/active.rb
new file mode 100644
index 000000000000..93a78add3542
--- /dev/null
+++ b/app/models/projects/exports/formatters/active.rb
@@ -0,0 +1,42 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2012-2024 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+module Projects::Exports
+ module Formatters
+ class Active < ::Exports::Formatters::Default
+ def self.apply?(attribute, export_format)
+ export_format == :pdf && %i[active].include?(attribute.to_sym)
+ end
+
+ ##
+ # Takes a project and returns yes/no depending on the active attribute
+ def format(project, **)
+ project.active? ? I18n.t(:general_text_Yes) : I18n.t(:general_text_No)
+ end
+ end
+ end
+end
diff --git a/app/models/projects/exports/formatters/public.rb b/app/models/projects/exports/formatters/public.rb
new file mode 100644
index 000000000000..deb4deb03011
--- /dev/null
+++ b/app/models/projects/exports/formatters/public.rb
@@ -0,0 +1,42 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2012-2024 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+module Projects::Exports
+ module Formatters
+ class Public < ::Exports::Formatters::Default
+ def self.apply?(attribute, export_format)
+ export_format == :pdf && %i[public].include?(attribute.to_sym)
+ end
+
+ ##
+ # Takes a project and returns yes/no depending on the public attribute
+ def format(project, **)
+ project.public? ? I18n.t(:general_text_Yes) : I18n.t(:general_text_No)
+ end
+ end
+ end
+end
diff --git a/app/models/work_package.rb b/app/models/work_package.rb
index b60f013478b4..0d32c30f11aa 100644
--- a/app/models/work_package.rb
+++ b/app/models/work_package.rb
@@ -294,6 +294,10 @@ def milestone?
alias_method :is_milestone?, :milestone?
+ def included_in_totals_calculation?
+ !status.excluded_from_totals
+ end
+
def done_ratio
if WorkPackage.use_status_for_done_ratio? && status && status.default_done_ratio
status.default_done_ratio
diff --git a/app/models/work_package/exports/macros/attributes.rb b/app/models/work_package/exports/macros/attributes.rb
new file mode 100644
index 000000000000..8b50adfa503e
--- /dev/null
+++ b/app/models/work_package/exports/macros/attributes.rb
@@ -0,0 +1,172 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2012-2024 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+module WorkPackage::Exports
+ module Macros
+ # OpenProject attribute macros syntax
+ # Examples:
+ # workPackageLabel:subject # Outputs work package label attribute "Subject"
+ # workPackageLabel:1234:subject # Outputs work package label attribute "Subject"
+
+ # workPackageValue:subject # Outputs the subject of the current work package
+ # workPackageValue:1234:subject # Outputs the subject of #1234
+ # workPackageValue:"custom field name" # Outputs the custom field value of the current work package
+ # workPackageValue:1234:"custom field name" # Outputs the custom field value of #1234
+ #
+ # projectLabel:active # Outputs current project label attribute "active"
+ # projectLabel:1234:active # Outputs project label attribute "active"
+ # projectLabel:my-project-identifier:active # Outputs project label attribute "active"
+
+ # projectValue:active # Outputs current project value for "active"
+ # projectValue:1234:active # Outputs project with id 1234 value for "active"
+ # projectValue:my-project-identifier:active # Outputs project with identifier my-project-identifier value for "active"
+ class Attributes < OpenProject::TextFormatting::Matchers::RegexMatcher
+ DISABLED_PROJECT_RICH_TEXT_FIELDS = %i[description status_explanation status_description].freeze
+ DISABLED_WORK_PACKAGE_RICH_TEXT_FIELDS = %i[description].freeze
+
+ def self.regexp
+ %r{
+ (\w+)(Label|Value) # The model type we try to reference
+ (?::(?:([^"\s]+)|"([^"]+)"))? # Optional: An ID or subject reference
+ (?::([^"\s.]+|"([^".]+)")) # The attribute name we're trying to reference
+ }x
+ end
+
+ ##
+ # Faster inclusion check before the regex is being applied
+ def self.applicable?(content)
+ content.include?("Label:") || content.include?("Value:")
+ end
+
+ def self.process_match(match, _matched_string, context)
+ context => { user:, work_package: }
+ type = match[2].downcase
+ model_s = match[1]
+ id = match[4] || match[3]
+ attribute = match[6] || match[5]
+ resolve_match(type, model_s, id, attribute, work_package, user)
+ end
+
+ def self.resolve_match(type, model_s, id, attribute, work_package, user)
+ if model_s == "workPackage"
+ resolve_work_package_match(id || work_package.id, type, attribute, user)
+ elsif model_s == "project"
+ resolve_project_match(id || work_package.project.id, type, attribute, user)
+ else
+ msg_macro_error I18n.t('export.macro.model_not_found', model: model_s)
+ end
+ end
+
+ def self.msg_macro_error(message)
+ msg_inline I18n.t('export.macro.error', message:)
+ end
+
+ def self.msg_macro_error_rich_text
+ msg_inline I18n.t('export.macro.rich_text_unsupported')
+ end
+
+ def self.msg_inline(message)
+ "[#{message}]"
+ end
+
+ def self.resolve_label_work_package(attribute)
+ resolve_label(WorkPackage, attribute)
+ end
+
+ def self.resolve_label_project(attribute)
+ resolve_label(Project, attribute)
+ end
+
+ def self.resolve_label(model, attribute)
+ model.human_attribute_name(
+ ::API::Utilities::PropertyNameConverter.to_ar_name(attribute.to_sym, context: model.new)
+ )
+ end
+
+ def self.resolve_work_package_match(id, type, attribute, user)
+ return resolve_label_work_package(attribute) if type == "label"
+ return msg_macro_error(I18n.t('export.macro.model_not_found', model: type)) unless type == "value"
+
+ work_package = WorkPackage.visible(user).find_by(id:)
+ if work_package.nil?
+ return msg_macro_error(I18n.t('export.macro.resource_not_found', resource: "#{WorkPackage.name} #{id}"))
+ end
+
+ resolve_value_work_package(work_package, attribute)
+ end
+
+ def self.resolve_project_match(id, type, attribute, user)
+ return resolve_label_project(attribute) if type == "label"
+ return msg_macro_error(I18n.t("export.macro.model_not_found", model: type)) unless type == "value"
+
+ project = Project.visible(user).find_by(id:)
+ project = Project.visible(user).find_by(identifier: id) if project.nil?
+ if project.nil?
+ return msg_macro_error(I18n.t("export.macro.resource_not_found", resource: "#{Project.name} #{id}"))
+ end
+
+ resolve_value_project(project, attribute)
+ end
+
+ def self.escape_tags(value)
+ # only disable html tags, but do not replace html entities
+ value.to_s.gsub("<", "<").gsub(">", ">")
+ end
+
+ def self.resolve_value_project(project, attribute)
+ resolve_value(project, attribute, DISABLED_PROJECT_RICH_TEXT_FIELDS)
+ end
+
+ def self.resolve_value_work_package(work_package, attribute)
+ resolve_value(work_package, attribute, DISABLED_WORK_PACKAGE_RICH_TEXT_FIELDS)
+ end
+
+ def self.resolve_value(obj, attribute, disabled_rich_text_fields)
+ cf = obj.available_custom_fields.find { |pcf| pcf.name == attribute }
+
+ return msg_macro_error_rich_text if cf&.formattable?
+
+ ar_name = if cf.nil?
+ ::API::Utilities::PropertyNameConverter.to_ar_name(attribute.to_sym, context: obj)
+ else
+ "cf_#{cf.id}"
+ end
+ return msg_macro_error_rich_text if disabled_rich_text_fields.include?(ar_name.to_sym)
+
+ format_attribute_value(ar_name, obj.class, obj)
+ end
+
+ def self.format_attribute_value(ar_name, model, obj)
+ formatter = Exports::Register.formatter_for(model, ar_name, :pdf)
+ value = formatter.format(obj)
+ # important NOT to return empty string as this could change meaning of markdown
+ # e.g. **to_be_replaced** could be rendered as **** (horizontal line and a *)
+ value.blank? ? " " : escape_tags(value)
+ end
+ end
+ end
+end
diff --git a/app/models/work_package/journalized.rb b/app/models/work_package/journalized.rb
index 2a8bac58a9aa..310e70c561c4 100644
--- a/app/models/work_package/journalized.rb
+++ b/app/models/work_package/journalized.rb
@@ -78,7 +78,7 @@ def self.event_url
url: JournalizedProcs.event_url
register_journal_formatted_fields(:id, "parent_id")
- register_journal_formatted_fields(:fraction,
+ register_journal_formatted_fields(:chronic_duration,
"estimated_hours", "derived_estimated_hours",
"remaining_hours", "derived_remaining_hours")
register_journal_formatted_fields(:percentage, "done_ratio", "derived_done_ratio")
diff --git a/app/models/work_package/pdf_export/markdown_field.rb b/app/models/work_package/pdf_export/markdown_field.rb
index 963396d30067..f5d45baa1dd5 100644
--- a/app/models/work_package/pdf_export/markdown_field.rb
+++ b/app/models/work_package/pdf_export/markdown_field.rb
@@ -28,6 +28,7 @@
module WorkPackage::PDFExport::MarkdownField
include WorkPackage::PDFExport::Markdown
+ PREFORMATTED_BLOCKS = %w(pre code).freeze
def write_markdown_field!(work_package, markdown, label)
return if markdown.blank?
@@ -37,7 +38,52 @@ def write_markdown_field!(work_package, markdown, label)
pdf.formatted_text([styles.wp_markdown_label.merge({ text: label })])
end
with_margin(styles.wp_markdown_margins) do
- write_markdown! work_package, markdown
+ write_markdown! work_package, apply_markdown_field_macros(markdown, work_package)
+ end
+ end
+
+ private
+
+ def apply_markdown_field_macros(markdown, work_package)
+ apply_macros(markdown, work_package, WorkPackage::Exports::Macros::Attributes)
+ end
+
+ def apply_macros(markdown, work_package, formatter)
+ return markdown unless formatter.applicable?(markdown)
+
+ document = Markly.parse(markdown)
+ document.walk do |node|
+ if node.type == :html
+ node.string_content = apply_macro_html(node.string_content, work_package, formatter) || node.string_content
+ elsif node.type == :text
+ node.string_content = apply_macro_text(node.string_content, work_package, formatter) || node.string_content
+ end
+ end
+ document.to_markdown
+ end
+
+ def apply_macro_text(text, work_package, formatter)
+ return text unless formatter.applicable?(text)
+
+ text.gsub!(formatter.regexp) do |matched_string|
+ matchdata = Regexp.last_match
+ formatter.process_match(matchdata, matched_string, { user: User.current, work_package: })
+ end
+ end
+
+ def apply_macro_html(html, work_package, formatter)
+ return html unless formatter.applicable?(html)
+
+ doc = Nokogiri::HTML.fragment(html)
+ apply_macro_html_node(doc, work_package, formatter)
+ doc.to_html
+ end
+
+ def apply_macro_html_node(node, work_package, formatter)
+ if node.text?
+ node.content = apply_macro_text(node.content, work_package, formatter)
+ elsif PREFORMATTED_BLOCKS.exclude?(node.name)
+ node.children.each { |child| apply_macro_html_node(child, work_package, formatter) }
end
end
end
diff --git a/app/models/work_package/pdf_export/work_package_detail.rb b/app/models/work_package/pdf_export/work_package_detail.rb
index 2d4aae33e8e7..632ea724c8fc 100644
--- a/app/models/work_package/pdf_export/work_package_detail.rb
+++ b/app/models/work_package/pdf_export/work_package_detail.rb
@@ -135,15 +135,19 @@ def form_configuration_columns(work_package)
end.flatten
end
- def form_key_to_column_entries(form_key, work_package)
- if CustomField.custom_field_attribute? form_key
- id = form_key.to_s.sub("custom_field_", "").to_i
- cf = CustomField.find_by(id:)
- return [] if cf.nil? || cf.formattable?
+ def form_key_custom_field_to_column_entries(form_key, work_package)
+ id = form_key.to_s.sub("custom_field_", "").to_i
+ cf = CustomField.find_by(id:)
+ return [] if cf.nil? || cf.formattable?
+
+ return [] unless cf.is_for_all? || work_package.project.work_package_custom_field_ids.include?(cf.id)
- return [] unless cf.is_for_all? || work_package.project.work_package_custom_field_ids.include?(cf.id)
+ [{ label: cf.name || form_key, name: form_key.to_s.sub("custom_field_", "cf_") }]
+ end
- return [{ label: cf.name || form_key, name: form_key }]
+ def form_key_to_column_entries(form_key, work_package)
+ if CustomField.custom_field_attribute? form_key
+ return form_key_custom_field_to_column_entries(form_key, work_package)
end
if form_key == :date
diff --git a/app/models/work_package/pdf_export/work_package_list_to_pdf.rb b/app/models/work_package/pdf_export/work_package_list_to_pdf.rb
index 7de6d091f45a..f933b5f6ee7d 100644
--- a/app/models/work_package/pdf_export/work_package_list_to_pdf.rb
+++ b/app/models/work_package/pdf_export/work_package_list_to_pdf.rb
@@ -73,7 +73,7 @@ def export!
rescue Prawn::Errors::CannotFit
error(I18n.t(:error_pdf_export_too_many_columns))
rescue StandardError => e
- Rails.logger.error { "Failed to generated PDF export: #{e}." }
+ Rails.logger.error { "Failed to generate PDF export: #{e}." }
error(I18n.t(:error_pdf_failed_to_export, error: e.message[0..300]))
end
diff --git a/app/services/duration_converter.rb b/app/services/duration_converter.rb
new file mode 100644
index 000000000000..0d6ddb66b049
--- /dev/null
+++ b/app/services/duration_converter.rb
@@ -0,0 +1,142 @@
+# frozen_string_literal: true
+
+# -- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2024 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+# ++
+
+# We use BigDecimal to handle floating point arithmetic and avoid
+# weird floating point results on decimal operations when converting
+# hours to seconds on duration outputting.
+require "bigdecimal"
+
+class DurationConverter
+ UNIT_ABBREVIATION_MAP = {
+ "seconds" => "seconds",
+ "second" => "seconds",
+ "secs" => "seconds",
+ "sec" => "seconds",
+ "s" => "seconds",
+ "minutes" => "minutes",
+ "minute" => "minutes",
+ "mins" => "minutes",
+ "min" => "minutes",
+ "m" => "minutes",
+ "hours" => "hours",
+ "hour" => "hours",
+ "hrs" => "hours",
+ "hr" => "hours",
+ "h" => "hours",
+ "days" => "days",
+ "day" => "days",
+ "dy" => "days",
+ "d" => "days",
+ "weeks" => "weeks",
+ "week" => "weeks",
+ "wks" => "weeks",
+ "wk" => "weeks",
+ "w" => "weeks",
+ "months" => "months",
+ "mo" => "months",
+ "mos" => "months",
+ "month" => "months",
+ "years" => "years",
+ "year" => "years",
+ "yrs" => "years",
+ "yr" => "years",
+ "y" => "years"
+ }.freeze
+
+ NEXT_UNIT_MAP = {
+ "years" => "months",
+ "months" => "weeks",
+ "weeks" => "days",
+ "days" => "hours",
+ "hours" => "minutes",
+ "minutes" => "seconds"
+ }.freeze
+
+ class << self
+ def parse(duration_string)
+ # Assume the next logical unit to allow users to write
+ # durations such as "2h 1" assuming "1" is "1 minute"
+ last_unit_in_string = duration_string.scan(/[a-zA-Z]+/)
+ .last
+ default_unit = if last_unit_in_string
+ last_unit_in_string
+ .then { |last_unit| UNIT_ABBREVIATION_MAP[last_unit.downcase] }
+ .then { |last_unit| NEXT_UNIT_MAP[last_unit] }
+ else
+ "hours"
+ end
+
+ ChronicDuration.raise_exceptions = true
+ ChronicDuration.parse(duration_string,
+ keep_zero: true,
+ default_unit:,
+ **duration_length_options) / 3600.to_f
+ end
+
+ def output(duration_in_hours)
+ return duration_in_hours if duration_in_hours.nil?
+
+ # Prevents rounding errors when including seconds by chopping
+ # off the overflow seconds and keeping the nearest minute.
+ seconds = ((duration_in_hours * 3600) + 30).to_i
+ seconds_overflow = seconds % 60
+ seconds_to_the_nearest_minute = seconds - seconds_overflow
+
+ # return "0 h" if parsing 0.
+ # ChronicDuration returns nil when parsing 0.
+ # By default, its unit is seconds and if we were
+ # keeping zeroes, we'd format this as "0 secs".
+ #
+ # We want to override this behavior.
+ if ChronicDuration.output(seconds_to_the_nearest_minute,
+ default_unit: "hours",
+ **duration_length_options).nil?
+ "0h"
+ else
+ ChronicDuration.output(seconds_to_the_nearest_minute,
+ default_unit: "hours",
+ format: :short,
+ **duration_length_options)
+ end
+ end
+
+ private
+
+ def convert_duration_to_seconds(duration_in_hours)
+ (BigDecimal(duration_in_hours.to_s) * 3600).to_f
+ end
+
+ def duration_length_options
+ { hours_per_day: Setting.hours_per_day,
+ days_per_month: Setting.days_per_month,
+ weeks: true }
+ end
+ end
+end
diff --git a/app/services/notifications/create_from_model_service.rb b/app/services/notifications/create_from_model_service.rb
index f51be96b0494..9f42b1a31f17 100644
--- a/app/services/notifications/create_from_model_service.rb
+++ b/app/services/notifications/create_from_model_service.rb
@@ -111,9 +111,9 @@ def create_notification(recipient_id, reason)
journal:,
actor: user_with_fallback,
reason:,
- read_ian: strategy.supports_ian? ? false : nil,
- mail_reminder_sent: strategy.supports_mail_digest? ? false : nil,
- mail_alert_sent: strategy.supports_mail? ? false : nil
+ read_ian: strategy.supports_ian?(reason) ? false : nil,
+ mail_reminder_sent: strategy.supports_mail_digest?(reason) ? false : nil,
+ mail_alert_sent: strategy.supports_mail?(reason) ? false : nil
}
Notifications::CreateService
@@ -129,7 +129,7 @@ def update_notification(recipient_id, reason)
Notifications::UpdateService
.new(model: existing_notification, user:, contract_class: EmptyContract)
- .call(read_ian: strategy.supports_ian? ? false : nil,
+ .call(read_ian: strategy.supports_ian?(reason) ? false : nil,
reason:)
end
@@ -288,24 +288,26 @@ def send_notification?(send_notifications)
end
def mention_matches
- text = text_for_mentions
-
- user_ids_tag_after,
- user_ids_tag_before,
- user_ids_hash,
- user_login_names,
- group_ids_tag_after,
- group_ids_tag_before,
- group_ids_hash = text
- .scan(MENTION_PATTERN)
- .transpose
- .each(&:compact!)
-
- {
- user_ids: [user_ids_tag_after, user_ids_tag_before, user_ids_hash].flatten.compact,
- user_login_names: [user_login_names].flatten.compact,
- group_ids: [group_ids_tag_after, group_ids_tag_before, group_ids_hash].flatten.compact
- }
+ @mention_matches ||= begin
+ text = text_for_mentions
+
+ user_ids_tag_after,
+ user_ids_tag_before,
+ user_ids_hash,
+ user_login_names,
+ group_ids_tag_after,
+ group_ids_tag_before,
+ group_ids_hash = text
+ .scan(MENTION_PATTERN)
+ .transpose
+ .each(&:compact!)
+
+ {
+ user_ids: [user_ids_tag_after, user_ids_tag_before, user_ids_hash].flatten.compact,
+ user_login_names: [user_login_names].flatten.compact,
+ group_ids: [group_ids_tag_after, group_ids_tag_before, group_ids_hash].flatten.compact
+ }
+ end
end
def abort_sending?
@@ -328,10 +330,16 @@ def add_receiver(receivers, collection, reason)
end
end
+ def user_not_mentioned_or_mentioned_indirectly(self_reason)
+ self_reason != NotificationSetting::MENTIONED ||
+ (mention_matches[:user_ids].exclude?(user_with_fallback.id) &&
+ mention_matches[:user_login_names].exclude?(user_with_fallback.login))
+ end
+
def remove_self_recipient(receivers)
if receivers.key?(user_with_fallback.id)
self_reasons = receivers[user_with_fallback.id]
- self_reasons.delete_if { |item| item != NotificationSetting::MENTIONED }
+ self_reasons.delete_if { |reason| user_not_mentioned_or_mentioned_indirectly(reason) }
if self_reasons.empty?
receivers.delete(user_with_fallback.id)
end
diff --git a/app/services/notifications/create_from_model_service/comment_strategy.rb b/app/services/notifications/create_from_model_service/comment_strategy.rb
index 1a3cd14f0611..dd139575ebd1 100644
--- a/app/services/notifications/create_from_model_service/comment_strategy.rb
+++ b/app/services/notifications/create_from_model_service/comment_strategy.rb
@@ -35,15 +35,15 @@ def self.permission
:view_news
end
- def self.supports_ian?
+ def self.supports_ian?(_reason)
false
end
- def self.supports_mail_digest?
+ def self.supports_mail_digest?(_reason)
false
end
- def self.supports_mail?
+ def self.supports_mail?(_reason)
true
end
diff --git a/app/services/notifications/create_from_model_service/message_strategy.rb b/app/services/notifications/create_from_model_service/message_strategy.rb
index eb34f9c56ca8..0e7084c09437 100644
--- a/app/services/notifications/create_from_model_service/message_strategy.rb
+++ b/app/services/notifications/create_from_model_service/message_strategy.rb
@@ -35,15 +35,15 @@ def self.permission
:view_messages
end
- def self.supports_ian?
+ def self.supports_ian?(_reason)
false
end
- def self.supports_mail_digest?
+ def self.supports_mail_digest?(_reason)
false
end
- def self.supports_mail?
+ def self.supports_mail?(_reason)
true
end
diff --git a/app/services/notifications/create_from_model_service/news_strategy.rb b/app/services/notifications/create_from_model_service/news_strategy.rb
index 38f963cd2960..2a2ae7d4ee47 100644
--- a/app/services/notifications/create_from_model_service/news_strategy.rb
+++ b/app/services/notifications/create_from_model_service/news_strategy.rb
@@ -35,15 +35,15 @@ def self.permission
:view_news
end
- def self.supports_ian?
+ def self.supports_ian?(_reason)
false
end
- def self.supports_mail_digest?
+ def self.supports_mail_digest?(_reason)
false
end
- def self.supports_mail?
+ def self.supports_mail?(_reason)
true
end
diff --git a/app/services/notifications/create_from_model_service/wiki_page_strategy.rb b/app/services/notifications/create_from_model_service/wiki_page_strategy.rb
index 8aadeaf57ca2..3dc3a8e36096 100644
--- a/app/services/notifications/create_from_model_service/wiki_page_strategy.rb
+++ b/app/services/notifications/create_from_model_service/wiki_page_strategy.rb
@@ -35,15 +35,15 @@ def self.permission
:view_wiki_pages
end
- def self.supports_ian?
+ def self.supports_ian?(_reason)
false
end
- def self.supports_mail_digest?
+ def self.supports_mail_digest?(_reason)
false
end
- def self.supports_mail?
+ def self.supports_mail?(_reason)
true
end
diff --git a/app/services/notifications/create_from_model_service/work_package_strategy.rb b/app/services/notifications/create_from_model_service/work_package_strategy.rb
index ff078b9aa168..c4150e8cf12b 100644
--- a/app/services/notifications/create_from_model_service/work_package_strategy.rb
+++ b/app/services/notifications/create_from_model_service/work_package_strategy.rb
@@ -35,16 +35,16 @@ def self.permission
:view_work_packages
end
- def self.supports_ian?
+ def self.supports_ian?(_reason)
true
end
- def self.supports_mail_digest?
+ def self.supports_mail_digest?(_reason)
true
end
- def self.supports_mail?
- true
+ def self.supports_mail?(reason)
+ reason == :mentioned
end
def self.watcher_users(journal)
diff --git a/app/services/project_custom_field_project_mappings/bulk_create_service.rb b/app/services/project_custom_field_project_mappings/bulk_create_service.rb
new file mode 100644
index 000000000000..f9bb4b7f530d
--- /dev/null
+++ b/app/services/project_custom_field_project_mappings/bulk_create_service.rb
@@ -0,0 +1,122 @@
+# frozen_string_literal: true
+
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2012-2024 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+module ProjectCustomFieldProjectMappings
+ class BulkCreateService < ::BaseServices::BaseCallable
+ def initialize(user:, project:, project_custom_field:, include_sub_projects: false)
+ super()
+ @user = user
+ @project = project
+ @project_custom_field = project_custom_field
+ @include_sub_projects = include_sub_projects
+ end
+
+ def perform
+ service_call = validate_permissions
+ service_call = validate_contract(service_call, incoming_mapping_ids) if service_call.success?
+ service_call = perform_bulk_create(service_call) if service_call.success?
+
+ service_call
+ end
+
+ private
+
+ def validate_permissions
+ if @user.allowed_in_project?(:select_project_custom_fields, projects)
+ ServiceResult.success
+ else
+ ServiceResult.failure(errors: { base: :error_unauthorized })
+ end
+ end
+
+ def validate_contract(service_call, project_ids)
+ set_attributes_results = project_ids.map do |id|
+ set_attributes(project_id: id, custom_field_id: @project_custom_field.id)
+ end
+
+ if (failures = set_attributes_results.select(&:failure?)).any?
+ service_call.success = false
+ service_call.errors = failures.map(&:errors)
+ else
+ service_call.result = set_attributes_results.map(&:result)
+ end
+
+ service_call
+ end
+
+ def perform_bulk_create(service_call)
+ ProjectCustomFieldProjectMapping.import(service_call.result, validate: false)
+
+ service_call
+ rescue StandardError => e
+ service_call.success = false
+ service_call.errors = e.message
+ end
+
+ def incoming_mapping_ids
+ project_ids = projects.pluck(:id)
+ project_ids - existing_project_mappings(project_ids)
+ end
+
+ def projects
+ [@project].tap do |projects_array|
+ projects_array.concat(@project.active_subprojects.to_a) if @include_sub_projects
+ end
+ end
+
+ def existing_project_mappings(project_ids)
+ ProjectCustomFieldProjectMapping.where(
+ custom_field_id: @project_custom_field.id,
+ project_id: project_ids
+ ).pluck(:project_id)
+ end
+
+ def set_attributes(params)
+ attributes_service_class
+ .new(user: @user,
+ model: instance(params),
+ contract_class: default_contract_class,
+ contract_options: {})
+ .call(params)
+ end
+
+ def instance(params)
+ ProjectCustomFieldProjectMapping.new(params)
+ end
+
+ def attributes_service_class
+ ProjectCustomFieldProjectMappings::SetAttributesService
+ end
+
+ def default_contract_class
+ ProjectCustomFieldProjectMappings::UpdateContract
+ end
+ end
+end
diff --git a/app/services/settings/update_service.rb b/app/services/settings/update_service.rb
index 836a7381ca2f..255f7af69bee 100644
--- a/app/services/settings/update_service.rb
+++ b/app/services/settings/update_service.rb
@@ -46,7 +46,7 @@ def set_setting_value(name, value)
new_value = derive_value(value)
Setting[name] = new_value
if name == :work_package_done_ratio && old_value != "status" && new_value == "status"
- WorkPackages::Progress::ApplyStatusesPCompleteJob.perform_later(cause_type: "progress_mode_changed_to_status_based")
+ WorkPackages::Progress::ApplyStatusesChangeJob.perform_later(cause_type: "progress_mode_changed_to_status_based")
end
end
diff --git a/app/services/settings/working_days_update_service.rb b/app/services/settings/working_days_and_hours_update_service.rb
similarity index 95%
rename from app/services/settings/working_days_update_service.rb
rename to app/services/settings/working_days_and_hours_update_service.rb
index 56575aed1e83..d3fe86a527bf 100644
--- a/app/services/settings/working_days_update_service.rb
+++ b/app/services/settings/working_days_and_hours_update_service.rb
@@ -26,7 +26,7 @@
# See COPYRIGHT and LICENSE files for more details.
#++
-class Settings::WorkingDaysUpdateService < Settings::UpdateService
+class Settings::WorkingDaysAndHoursUpdateService < Settings::UpdateService
def call(params)
params = params.to_h.deep_symbolize_keys
self.non_working_days_params = params.delete(:non_working_days) || []
@@ -36,7 +36,7 @@ def call(params)
end
def validate_params(params)
- contract = Settings::WorkingDaysParamsContract.new(model, user, params:)
+ contract = Settings::WorkingDaysAndHoursParamsContract.new(model, user, params:)
ServiceResult.new success: contract.valid?,
errors: contract.errors,
result: model
diff --git a/app/services/work_packages/update_ancestors/loader.rb b/app/services/work_packages/update_ancestors/loader.rb
index 435301050231..3e9646e5f99e 100644
--- a/app/services/work_packages/update_ancestors/loader.rb
+++ b/app/services/work_packages/update_ancestors/loader.rb
@@ -25,6 +25,22 @@
# See COPYRIGHT and LICENSE files for more details.
class WorkPackages::UpdateAncestors::Loader
+ DESCENDANT_ATTRIBUTES = {
+ id: "id",
+ parent_id: "parent_id",
+ estimated_hours: "estimated_hours",
+ remaining_hours: "remaining_hours",
+ status_excluded_from_totals: "statuses.excluded_from_totals",
+ schedule_manually: "schedule_manually",
+ ignore_non_working_days: "ignore_non_working_days"
+ }.freeze
+
+ WorkPackageLikeStruct = Data.define(*DESCENDANT_ATTRIBUTES.keys) do
+ def included_in_totals_calculation?
+ !status_excluded_from_totals
+ end
+ end
+
def initialize(work_package, include_former_ancestors)
self.work_package = work_package
self.include_former_ancestors = include_former_ancestors
@@ -40,7 +56,7 @@ def select
def descendants_of(queried_work_package)
@descendants ||= Hash.new do |hash, wp|
- hash[wp] = replaced_related_of(wp, :descendants)
+ hash[wp] = replaced_related_descendants(wp)
end
@descendants[queried_work_package]
@@ -72,7 +88,7 @@ def ancestors
end
end
- # Replace descendants/leaves by ancestors if they are the same.
+ # Replace descendants by ancestors if they are the same.
# This can e.g. be the case in scenario of
# grandparent
# |
@@ -84,31 +100,27 @@ def ancestors
# Then grandparent and parent are already in ancestors.
# Parent might be modified during the UpdateAncestorsService run,
# and the descendants of grandparent need to have the updated value.
- def replaced_related_of(queried_work_package, relation_type)
- related_of(queried_work_package, relation_type).map do |leaf|
+ def replaced_related_descendants(queried_work_package)
+ related_descendants(queried_work_package).map do |leaf|
if work_package.id == leaf.id
work_package
elsif (ancestor = ancestors.detect { |a| a.id == leaf.id })
ancestor
else
- yield leaf if block_given?
leaf
end
end
end
- def related_of(queried_work_package, relation_type)
+ def related_descendants(queried_work_package)
scope = queried_work_package
- .send(relation_type)
+ .descendants
.where.not(id: queried_work_package.id)
- if send(:"#{relation_type}_joins")
- scope = scope.joins(send(:"#{relation_type}_joins"))
- end
-
scope
- .pluck(*send(:"selected_#{relation_type}_attributes"))
- .map { |p| LoaderStruct.new(send(:"selected_#{relation_type}_attributes").zip(p).to_h) }
+ .left_joins(:status)
+ .pluck(*DESCENDANT_ATTRIBUTES.values)
+ .map { |p| WorkPackageLikeStruct.new(**DESCENDANT_ATTRIBUTES.keys.zip(p).to_h) }
end
# Returns the current ancestors sorted by distance (called generations in the table)
@@ -128,23 +140,6 @@ def former_ancestors
end
end
- def selected_descendants_attributes
- # By having the id in here, we can avoid DISTINCT queries squashing duplicate values
- %i(id estimated_hours parent_id schedule_manually ignore_non_working_days remaining_hours)
- end
-
- def descendants_joins
- nil
- end
-
- def selected_leaves_attributes
- %i(id done_ratio derived_estimated_hours estimated_hours is_closed remaining_hours derived_remaining_hours)
- end
-
- def leaves_joins
- :status
- end
-
##
# Get the previous parent ID
# This could either be +parent_id_was+ if parent was changed
@@ -165,9 +160,6 @@ def previous_change_parent_id
previous_parent_changes = previous[:parent_id] || previous[:parent]
- previous_parent_changes ? previous_parent_changes.first : nil
+ previous_parent_changes&.first
end
-
- class LoaderStruct < Hashie::Mash; end
- LoaderStruct.disable_warnings
end
diff --git a/app/services/work_packages/update_ancestors_service.rb b/app/services/work_packages/update_ancestors_service.rb
index 7627840b4886..0ced628eac74 100644
--- a/app/services/work_packages/update_ancestors_service.rb
+++ b/app/services/work_packages/update_ancestors_service.rb
@@ -99,7 +99,7 @@ def derive_attributes(work_package, loader, attributes)
# or the derived remaining hours, depending on the % Complete mode
# currently active.
#
- %i[estimated_hours remaining_hours] => :derive_total_estimated_and_remaining_hours,
+ %i[estimated_hours remaining_hours status status_id] => :derive_total_estimated_and_remaining_hours,
%i[estimated_hours remaining_hours done_ratio status status_id] => :derive_done_ratio,
%i[ignore_non_working_days] => :derive_ignore_non_working_days
}.each do |derivative_attributes, method|
@@ -155,7 +155,9 @@ def derive_total(work_package, attribute, loader)
return if no_children?(work_package, loader)
work_packages = [work_package] + loader.descendants_of(work_package)
- values = work_packages.filter_map(&attribute)
+ values = work_packages
+ .filter(&:included_in_totals_calculation?)
+ .filter_map(&attribute)
return if values.empty?
values.sum.to_f
diff --git a/app/views/admin/index.html.erb b/app/views/admin/index.html.erb
index d318b2fb6be9..9f67f397c8da 100644
--- a/app/views/admin/index.html.erb
+++ b/app/views/admin/index.html.erb
@@ -34,7 +34,7 @@ See COPYRIGHT and LICENSE files for more details.
<% @menu_nodes.each do |menu_node| -%>
<%= link_to menu_node.url, { class: 'menu-block', 'data-test-selector': 'menu-block' } do %>
- <%= op_icon("menu-block--icon icon3 icon-#{(menu_node.icon || '')}") %>
+ <%= spot_icon("#{(menu_node.icon || '')}", classnames: "menu-block--icon icon3") %>
<%= menu_node.caption %>
<% end %>
<% end %>
diff --git a/app/views/admin/settings/project_custom_fields/index.html.erb b/app/views/admin/settings/project_custom_fields/index.html.erb
index 71c74dbe15b5..28a58287d6c1 100644
--- a/app/views/admin/settings/project_custom_fields/index.html.erb
+++ b/app/views/admin/settings/project_custom_fields/index.html.erb
@@ -29,7 +29,7 @@ See COPYRIGHT and LICENSE files for more details.
<% html_title t(:label_administration), t("settings.project_attributes.heading") %>
- <%= render(Settings::ProjectCustomFields::HeaderComponent.new()) %>
+ <%= render(Settings::ProjectCustomFields::HeaderComponent.new) %>
<%= render(Settings::ProjectCustomFieldSections::IndexComponent.new(
project_custom_field_sections: @project_custom_field_sections
)) %>
diff --git a/app/views/admin/settings/project_custom_fields/project_mappings.html.erb b/app/views/admin/settings/project_custom_fields/project_mappings.html.erb
index 281029ea5810..d97890b6652e 100644
--- a/app/views/admin/settings/project_custom_fields/project_mappings.html.erb
+++ b/app/views/admin/settings/project_custom_fields/project_mappings.html.erb
@@ -27,6 +27,11 @@ See COPYRIGHT and LICENSE files for more details.
++#%>
+<% content_controller 'projects--settings--available-project-mappings-filter',
+ dynamic: true
+%>
+
+
<%=
render(Settings::ProjectCustomFields::EditFormHeaderComponent.new(
custom_field: @custom_field,
@@ -34,6 +39,30 @@ See COPYRIGHT and LICENSE files for more details.
))
%>
+<%=
+ render(Primer::OpenProject::SubHeader.new) do |component|
+ component.with_filter_input(
+ name: "available-project-mappings-filter",
+ label: I18n.t("projects.settings.project_custom_fields.project_mapping_filter.label"),
+ visually_hide_label: true,
+ placeholder: I18n.t("projects.settings.project_custom_fields.project_mapping_filter.placeholder"),
+ show_clear_button: true,
+ clear_button_id: "available-project-mappings-filter-clear-button",
+ data: {
+ action: "input->projects--settings--available-project-mappings-filter#filterLists",
+ "projects--settings--available-project-mappings-filter-target": "filter"
+ }
+ )
+
+ component.with_action_component do
+ render(Settings::ProjectCustomFields::ProjectCustomFieldMapping::NewProjectMappingComponent.new(
+ project_mapping: @project_mapping,
+ project_custom_field: @custom_field
+ ))
+ end
+ end unless @custom_field.required?
+%>
+
<%=
if @custom_field.required?
render Primer::Beta::Blankslate.new(border: true) do |component|
diff --git a/app/views/admin/settings/work_packages_settings/show.html.erb b/app/views/admin/settings/work_packages_settings/show.html.erb
index 0151e41e51fa..9c8031bba8e6 100644
--- a/app/views/admin/settings/work_packages_settings/show.html.erb
+++ b/app/views/admin/settings/work_packages_settings/show.html.erb
@@ -32,16 +32,27 @@ See COPYRIGHT and LICENSE files for more details.
<%= toolbar title: t(:label_work_package_tracking) %>
<%= styled_form_tag({ action: :update }, method: :patch) do %>
-
+
<%= setting_select(:work_package_list_default_highlighting_mode,
Query::Highlighting::QUERY_HIGHLIGHTING_MODES.map do |mode|
diff --git a/app/views/admin/settings/working_days_settings/show.html.erb b/app/views/admin/settings/working_days_and_hours_settings/show.html.erb
similarity index 51%
rename from app/views/admin/settings/working_days_settings/show.html.erb
rename to app/views/admin/settings/working_days_and_hours_settings/show.html.erb
index da9d61f9fc0e..26e2c8552c95 100644
--- a/app/views/admin/settings/working_days_settings/show.html.erb
+++ b/app/views/admin/settings/working_days_and_hours_settings/show.html.erb
@@ -27,37 +27,65 @@ See COPYRIGHT and LICENSE files for more details.
++#%>
-<%= toolbar title: t(:label_working_days) %>
-
-
-
-
- <%= t("working_days.warning").html_safe %>
-
-
-
+<%= toolbar title: t(:label_working_days_and_hours) %>
<%= styled_form_tag(
- admin_settings_working_days_path,
+ admin_settings_working_days_and_hours_path,
method: :patch,
class: 'op-working-days-admin-settings'
) do %>
+
+
+
+
@@ -66,7 +94,7 @@ See COPYRIGHT and LICENSE files for more details.
+
<%= render partial: "/colors/color_autocomplete_field",
locals: {
form: f,
diff --git a/app/workers/notifications/with_marked_notifications.rb b/app/workers/notifications/with_marked_notifications.rb
index e56639dc620a..e99d1b2e63b2 100644
--- a/app/workers/notifications/with_marked_notifications.rb
+++ b/app/workers/notifications/with_marked_notifications.rb
@@ -37,16 +37,21 @@ module WithMarkedNotifications
def with_marked_notifications(notification_ids)
Notification.transaction do
- mark_notifications_sent(notification_ids)
+ # It might be decided by the callers that the notifications should not be sent after all which
+ # is signaled by `nil`. This happens e.g. for work packages where users might have disabled the
+ # immediate_reminders for mentioned.
+ was_sent = yield
- yield
+ mark_notifications_sent(notification_ids, was_sent.present? ? !!was_sent : nil)
+
+ was_sent
end
end
- def mark_notifications_sent(notification_ids)
+ def mark_notifications_sent(notification_ids, was_sent)
Notification
.where(id: Array(notification_ids))
- .update_all(notification_marked_attribute => true, updated_at: Time.current)
+ .update_all(notification_marked_attribute => was_sent, updated_at: Time.current)
end
end
end
diff --git a/app/workers/work_packages/progress/apply_statuses_p_complete_job.rb b/app/workers/work_packages/progress/apply_statuses_change_job.rb
similarity index 60%
rename from app/workers/work_packages/progress/apply_statuses_p_complete_job.rb
rename to app/workers/work_packages/progress/apply_statuses_change_job.rb
index e85e3b0cca63..a2ef5e1b8688 100644
--- a/app/workers/work_packages/progress/apply_statuses_p_complete_job.rb
+++ b/app/workers/work_packages/progress/apply_statuses_change_job.rb
@@ -28,34 +28,40 @@
# See COPYRIGHT and LICENSE files for more details.
#++
-class WorkPackages::Progress::ApplyStatusesPCompleteJob < WorkPackages::Progress::Job
+class WorkPackages::Progress::ApplyStatusesChangeJob < WorkPackages::Progress::Job
VALID_CAUSE_TYPES = %w[
progress_mode_changed_to_status_based
- status_p_complete_changed
+ status_changed
].freeze
+ attr_reader :cause_type, :status_name, :status_id, :changes
+
# Updates % complete and remaining work of all work packages after a status %
# complete value has been changed or the progress calculation mode was set to
# status-based.
#
- # It creates a journal entry with the System user describing the change.
+ # It creates a journal entry with the System user describing the changes.
#
# @param status_name [String] The cause of the update to be put in the journal
# entry. Must be one of `VALID_CAUSE_TYPES`.
# @param status_name [String] The name of the status to apply.
# @param status_id [Integer] The ID of the status to apply. Not used
# currently, but here in case we need it in a later version.
- # @param change [Object] The change object containing an array of [old, new]
- # values of the change.
+ # @param changes [Object] The changes object containing a map of array of
+ # [old, new] values of the change, for instance
+ # `{"default_done_ratio" => [20, 40], "excluded_from_totals" => [false, true]}`.
# @return [void]
- def perform(cause_type:, status_name: nil, status_id: nil, change: nil)
- return if WorkPackage.use_field_for_done_ratio?
-
- journal_cause = journal_cause_from(cause_type, status_name:, status_id:, change:)
+ def perform(cause_type:, status_name: nil, status_id: nil, changes: nil)
+ @cause_type = cause_type
+ @status_name = status_name
+ @status_id = status_id
+ @changes = changes
with_temporary_progress_table do
- set_p_complete_from_status
- derive_remaining_work_from_work_and_p_complete
+ if WorkPackage.use_status_for_done_ratio?
+ set_p_complete_from_status
+ derive_remaining_work_from_work_and_p_complete
+ end
update_totals
copy_progress_values_to_work_packages_and_update_journals(journal_cause)
@@ -64,23 +70,43 @@ def perform(cause_type:, status_name: nil, status_id: nil, change: nil)
private
- def journal_cause_from(cause_type, status_name:, status_id:, change:)
- if VALID_CAUSE_TYPES.exclude?(cause_type)
+ def journal_cause
+ assert_valid_cause_type!
+
+ @journal_cause ||=
+ case cause_type
+ when "progress_mode_changed_to_status_based"
+ Journal::CausedByProgressModeChangedToStatusBased.new
+ when "status_changed"
+ assert_status_information_present!
+ Journal::CausedByStatusChanged.new(
+ status_name:,
+ status_id:,
+ status_changes: changes
+ )
+ else
+ raise "Unable to handle cause type #{cause_type.inspect}"
+ end
+ end
+
+ def assert_valid_cause_type!
+ unless VALID_CAUSE_TYPES.include?(cause_type)
raise ArgumentError, "Invalid cause type #{cause_type.inspect}. " \
"Valid values are #{VALID_CAUSE_TYPES.inspect}"
end
+ end
+
+ def assert_status_information_present!
+ if status_name.blank?
+ raise ArgumentError, "status_name must be provided"
+ end
- case cause_type
- when "progress_mode_changed_to_status_based"
- { type: cause_type }
- when "status_p_complete_changed"
- raise ArgumentError, "status_name must be provided" if status_name.blank?
- raise ArgumentError, "status_id must be provided" if status_id.nil?
- raise ArgumentError, "change must be provided" if change.nil?
+ if status_id.nil?
+ raise ArgumentError, "status_id must be provided"
+ end
- { type: cause_type, status_name:, status_id:, status_p_complete_change: change }
- else
- raise "Unable to handle cause type #{cause_type.inspect}"
+ if changes.nil?
+ raise ArgumentError, "changes must be provided"
end
end
end
diff --git a/app/workers/work_packages/progress/migrate_remove_totals_from_childless_work_packages_job.rb b/app/workers/work_packages/progress/migrate_remove_totals_from_childless_work_packages_job.rb
index d49f81493b8d..d01e42f7f567 100644
--- a/app/workers/work_packages/progress/migrate_remove_totals_from_childless_work_packages_job.rb
+++ b/app/workers/work_packages/progress/migrate_remove_totals_from_childless_work_packages_job.rb
@@ -27,6 +27,8 @@
#++
class WorkPackages::Progress::MigrateRemoveTotalsFromChildlessWorkPackagesJob < WorkPackages::Progress::Job
+ include WorkPackages::Progress::SqlCommandsForMigration
+
def perform
updated_work_package_ids = remove_totals_from_childless_work_packages
create_journals_for_updated_work_packages(updated_work_package_ids, cause: journal_cause)
diff --git a/app/workers/work_packages/progress/migrate_values_job.rb b/app/workers/work_packages/progress/migrate_values_job.rb
index 6e77ee790e3f..212f912d8244 100644
--- a/app/workers/work_packages/progress/migrate_values_job.rb
+++ b/app/workers/work_packages/progress/migrate_values_job.rb
@@ -27,6 +27,8 @@
#++
class WorkPackages::Progress::MigrateValuesJob < WorkPackages::Progress::Job
+ include WorkPackages::Progress::SqlCommandsForMigration
+
attr_reader :current_mode, :previous_mode
def perform(current_mode:, previous_mode:)
diff --git a/app/workers/work_packages/progress/sql_commands.rb b/app/workers/work_packages/progress/sql_commands.rb
index 9ad890a17690..1b2b6990825b 100644
--- a/app/workers/work_packages/progress/sql_commands.rb
+++ b/app/workers/work_packages/progress/sql_commands.rb
@@ -96,15 +96,21 @@ def update_totals
END
FROM (
SELECT wp_tree.ancestor_id AS id,
- MAX(generations) AS generations,
SUM(estimated_hours) AS total_work,
SUM(remaining_hours) AS total_remaining_work
FROM work_package_hierarchies wp_tree
LEFT JOIN temp_wp_progress_values wp_progress ON wp_tree.descendant_id = wp_progress.id
+ LEFT JOIN statuses ON wp_progress.status_id = statuses.id
+ WHERE statuses.excluded_from_totals = FALSE
GROUP BY wp_tree.ancestor_id
) totals
WHERE temp_wp_progress_values.id = totals.id
- AND totals.generations > 0
+ AND temp_wp_progress_values.id IN (
+ SELECT ancestor_id AS id
+ FROM work_package_hierarchies
+ GROUP BY id
+ HAVING MAX(generations) > 0
+ )
SQL
end
diff --git a/app/workers/work_packages/progress/sql_commands_for_migration.rb b/app/workers/work_packages/progress/sql_commands_for_migration.rb
new file mode 100644
index 000000000000..6842c7e22543
--- /dev/null
+++ b/app/workers/work_packages/progress/sql_commands_for_migration.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2012-2024 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+# Specific SQL commands for updating work package progress values during
+# migrations, as some methods in `WorkPackages::Progress::SqlCommands` rely on
+# fields that may not exist yet.
+module WorkPackages::Progress::SqlCommandsForMigration
+ # Computes total work, total remaining work and total % complete for all work
+ # packages having children.
+ def update_totals
+ execute(<<~SQL.squish)
+ UPDATE temp_wp_progress_values
+ SET total_work = totals.total_work,
+ total_remaining_work = totals.total_remaining_work,
+ total_p_complete = CASE
+ WHEN totals.total_work = 0 THEN NULL
+ ELSE (1 - (totals.total_remaining_work / totals.total_work)) * 100
+ END
+ FROM (
+ SELECT wp_tree.ancestor_id AS id,
+ MAX(generations) AS generations,
+ SUM(estimated_hours) AS total_work,
+ SUM(remaining_hours) AS total_remaining_work
+ FROM work_package_hierarchies wp_tree
+ LEFT JOIN temp_wp_progress_values wp_progress ON wp_tree.descendant_id = wp_progress.id
+ GROUP BY wp_tree.ancestor_id
+ ) totals
+ WHERE temp_wp_progress_values.id = totals.id
+ AND totals.generations > 0
+ SQL
+ end
+end
diff --git a/config/constants/settings/definition.rb b/config/constants/settings/definition.rb
index 8fef00702ad9..038088dc084f 100644
--- a/config/constants/settings/definition.rb
+++ b/config/constants/settings/definition.rb
@@ -303,6 +303,12 @@ class Definition
"%B %d, %Y"
].freeze
},
+ days_per_month: {
+ description: "This will define what is considered a “month” when displaying duration in a more natural way " \
+ "(for example, if a month is 20 days, 60 days would be 3 months.",
+ default: 20,
+ format: :integer
+ },
default_auto_hide_popups: {
description: "Whether to automatically hide success notifications by default",
default: true
@@ -521,6 +527,18 @@ class Definition
host_name: {
default: "localhost:3000"
},
+ hours_per_day: {
+ description: "This will define what is considered a “day” when displaying duration in a more natural way " \
+ "(for example, if a day is 8 hours, 32 hours would be 4 days).",
+ default: 8,
+ format: :integer
+ },
+ days_per_week: {
+ description: "This will define what is considered a “week” when displaying duration in a more natural way " \
+ "(for example, if a week is 5 days, 15 days would be 3 weeks).",
+ default: 5,
+ format: :integer
+ },
# Health check configuration
health_checks_authentication_password: {
description: "Add an authentication challenge for the /health_check endpoint",
diff --git a/config/initializers/export_formats.rb b/config/initializers/export_formats.rb
index f95759cdf163..9d7603cef5e9 100644
--- a/config/initializers/export_formats.rb
+++ b/config/initializers/export_formats.rb
@@ -15,11 +15,15 @@
formatter WorkPackage, WorkPackage::Exports::Formatters::Costs
formatter WorkPackage, WorkPackage::Exports::Formatters::DoneRatio
formatter WorkPackage, Exports::Formatters::CustomField
+ formatter WorkPackage, Exports::Formatters::CustomFieldPdf
list Project, Projects::Exports::CSV
formatter Project, Exports::Formatters::CustomField
+ formatter Project, Exports::Formatters::CustomFieldPdf
formatter Project, Projects::Exports::Formatters::Status
formatter Project, Projects::Exports::Formatters::Description
+ formatter Project, Projects::Exports::Formatters::Public
+ formatter Project, Projects::Exports::Formatters::Active
end
end
end
diff --git a/config/initializers/menus.rb b/config/initializers/menus.rb
index c71ea9bea60d..160e294296d9 100644
--- a/config/initializers/menus.rb
+++ b/config/initializers/menus.rb
@@ -238,9 +238,9 @@
menu.push :users,
{ controller: "/users" },
if: Proc.new {
- !User.current.admin? &&
- (User.current.allowed_globally?(:manage_user) || User.current.allowed_globally?(:create_user))
- },
+ !User.current.admin? &&
+ (User.current.allowed_globally?(:manage_user) || User.current.allowed_globally?(:create_user))
+ },
caption: :label_user_plural,
icon: "group"
@@ -380,15 +380,15 @@
icon: "enumerations"
menu.push :calendars_and_dates,
- { controller: "/admin/settings/working_days_settings", action: :show },
+ { controller: "/admin/settings/working_days_and_hours_settings", action: :show },
if: Proc.new { User.current.admin? },
caption: :label_calendars_and_dates,
icon: "calendar"
- menu.push :working_days,
- { controller: "/admin/settings/working_days_settings", action: :show },
+ menu.push :working_days_and_hours,
+ { controller: "/admin/settings/working_days_and_hours_settings", action: :show },
if: Proc.new { User.current.admin? },
- caption: :label_working_days,
+ caption: :label_working_days_and_hours,
parent: :calendars_and_dates
menu.push :date_format,
diff --git a/config/initializers/primer_forms.rb b/config/initializers/primer_forms.rb
index d1689df7d3e5..e501a716b779 100644
--- a/config/initializers/primer_forms.rb
+++ b/config/initializers/primer_forms.rb
@@ -2,4 +2,5 @@
Rails.application.config.to_prepare do
Primer::Forms::Dsl::FormObject.include(Primer::OpenProject::Forms::Dsl::InputMethods)
+ Primer::Forms::Dsl::InputGroup.include(Primer::OpenProject::Forms::Dsl::InputMethods)
end
diff --git a/config/locales/crowdin/af.yml b/config/locales/crowdin/af.yml
index 35a623cddcbe..4430e652b1ed 100644
--- a/config/locales/crowdin/af.yml
+++ b/config/locales/crowdin/af.yml
@@ -300,6 +300,12 @@ af:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: There are currently no types available.
form:
@@ -448,12 +454,20 @@ af:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: There are currently no work package statuses.
no_results_content_text: Add a new status
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -623,6 +637,7 @@ af:
status:
is_closed: "Werk pakket geslote"
is_readonly: "Work package read-only"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Notas"
member:
@@ -959,6 +974,14 @@ af:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1143,18 +1166,6 @@ af:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Verskilstelle"
message: "Forums"
@@ -1605,6 +1616,12 @@ af:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1658,7 +1675,7 @@ af:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1675,8 +1692,9 @@ af:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2333,7 +2351,7 @@ af:
label_workflow: "Werksvloei"
label_workflow_plural: "Workflows"
label_workflow_summary: "Opsomming"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 closed"
other: "%{count} closed"
@@ -2933,6 +2951,9 @@ af:
setting_cross_project_work_package_relations: "Allow cross-project work package relations"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "Datum"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Default language"
setting_default_projects_modules: "Default enabled modules for new projects"
setting_default_projects_public: "Nuwe projekte is openbaar by verstek"
@@ -2948,6 +2969,12 @@ af:
setting_feeds_limit: "Feed content limit"
setting_file_max_size_displayed: "Max size of text files displayed inline"
setting_host_name: "Host name"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3389,12 +3416,12 @@ af:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/ar.yml b/config/locales/crowdin/ar.yml
index 8d96903520c7..5364ffea99ef 100644
--- a/config/locales/crowdin/ar.yml
+++ b/config/locales/crowdin/ar.yml
@@ -300,6 +300,12 @@ ar:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: لا يوجد حالياً أي أنواع متاحة.
form:
@@ -472,12 +478,20 @@ ar:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: لا يوجد حالياً حالات لحزمة العمل.
no_results_content_text: إضافة حالة جديدة
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -651,6 +665,7 @@ ar:
status:
is_closed: "أغلقت مجموعة العمل"
is_readonly: "Work package read-only"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "ملاحظات"
member:
@@ -987,6 +1002,14 @@ ar:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1203,18 +1226,6 @@ ar:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "مجموعة التغييرات"
message: "منتديات"
@@ -1737,6 +1748,12 @@ ar:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1790,7 +1807,7 @@ ar:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1807,8 +1824,9 @@ ar:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2465,7 +2483,7 @@ ar:
label_workflow: "سير العمل"
label_workflow_plural: "تدفقات العمل"
label_workflow_summary: "مُلخّص"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 مغلقة"
other: "%{count} مغلق"
@@ -2546,7 +2564,7 @@ ar:
few: "There are %{count} more work packages with notifications."
many: "There are %{count} more work packages with notifications."
other: "There are %{count} more work packages with notifications."
- open_in_browser: "Open in browser"
+ open_in_browser: "فتح في المتصفح"
reason:
watched: "Watched"
assigned: "Assigned"
@@ -2613,8 +2631,8 @@ ar:
mail_body_lost_password: "لتغيير كلمة المرور الخاصة بك، انقر فوق الارتباط التالي:"
mail_password_change_not_possible:
title: "Password change not possible"
- body: "Your account at %{app_title} is connected to an external authentication provider (%{name})."
- subtext: "Passwords for external account cannot be changed in the application. Please use the lost password functionality of your authentication provider."
+ body: "حسابك في %{app_title} متصل بمزود مصادقة خارجي (%{name})."
+ subtext: "لا يمكن تغيير كلمات المرور للحساب الخارجي في التطبيق. يرجى استخدام وظيفة فقدان كلمة المرور الخاصة بموفر المصادقة لديك."
mail_body_register: "Welcome to %{app_title}. Please activate your account by clicking on this link:"
mail_body_register_header_title: "Project member invitation email"
mail_body_register_user: "Dear %{name}, "
@@ -2770,7 +2788,7 @@ ar:
permission_add_work_package_notes: "إضافة ملاحظات"
permission_add_work_packages: "إضافة مجموعات عمل"
permission_add_messages: "نشر الرسائل"
- permission_add_project: "Create projects"
+ permission_add_project: "أنشئ مشروعات"
permission_add_work_package_attachments: "إضافة مرفقات"
permission_add_work_package_attachments_explanation: "Allows adding attachments without Edit work packages permission"
permission_archive_project: "Archive project"
@@ -2788,7 +2806,7 @@ ar:
permission_commit_access: "الوصول للقراءة/الكتابة إلى المستودع (الالتزام)"
permission_copy_projects: "نسخ المشاريع"
permission_copy_work_packages: "انسخ مجموعات العمل"
- permission_create_backup: "Create backups"
+ permission_create_backup: "انشيئ نسخ احتياطية"
permission_delete_work_package_watchers: "حذف مراقبات"
permission_delete_work_packages: "حذف مجموعات العمل"
permission_delete_messages: "حذف الرسائل"
@@ -2805,14 +2823,14 @@ ar:
permission_edit_own_time_entries: "تحرير سجلات الوقت الخاصة"
permission_edit_project: "تحرير المشروع"
permission_edit_reportings: "تحرير التقرير"
- permission_edit_time_entries: "Edit time logs for other users"
+ permission_edit_time_entries: "تحرير سجلات الوقت للمستخدمين الآخرين"
permission_edit_timelines: "تحرير الجداول الزمنية"
permission_edit_wiki_pages: "تحرير صفحات wiki"
permission_export_work_packages: "تصدير مجموعات العمل"
permission_export_wiki_pages: "تصدير صفحات wiki"
permission_list_attachments: "قائمة المرفقات"
- permission_log_own_time: "Log own time"
- permission_log_time: "Log time for other users"
+ permission_log_own_time: "تسجيل الوقت الخاص بك"
+ permission_log_time: "تسجيل الوقت للمستخدمين الآخرين"
permission_manage_forums: "إدارة منتديات"
permission_manage_categories: "إدارة فئات مجموعة العمل"
permission_manage_dashboards: "Manage dashboards"
@@ -2892,7 +2910,7 @@ ar:
project_module_news: "الأخبار"
project_module_repository: "مستودع البيانات"
project_module_wiki: "Wiki"
- permission_header_for_project_module_work_package_tracking: "Work packages and Gantt charts"
+ permission_header_for_project_module_work_package_tracking: "حزم العمل ومخططات Gantt"
query:
attribute_and_direction: "%{attribute} (%{direction})"
#possible query parameters (e.g. issue queries),
@@ -2904,7 +2922,7 @@ ar:
member_of_group: "مجموعة الموكل إليه"
name_or_identifier: "Name or identifier"
only_subproject_id: "Only subproject"
- shared_with_user: "Shared with users"
+ shared_with_user: "مشترك مع المستخدمين"
shared_with_me: "Shared with me"
subproject_id: "Including subproject"
repositories:
@@ -2994,7 +3012,7 @@ ar:
oauth_application_details_link_text: "Go to settings page"
setup_documentation_details: "If you need help configuring a new file storage please check the documentation: "
setup_documentation_details_link_text: "File Storages setup"
- show_warning_details: "To use this file storage remember to activate the module and the specific storage in the project settings of each desired project."
+ show_warning_details: "لاستخدام هذا التخزين للملفات، تذكر تفعيل الوحدة والتخزين المحدد في إعدادات المشروع لكل مشروع مرغوب."
subversion:
existing_title: "مستودع التخريب موجود"
existing_introduction: "إذا كان لديك مستودع بوابة محلية القائمة، يمكنك ربطه مع open project للوصول إليها من داخل التطبيق."
@@ -3071,6 +3089,9 @@ ar:
setting_cross_project_work_package_relations: "السماح بعلاقات عبر-المشروع مجموعة العمل"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "التاريخ"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "اللغة الافتراضية"
setting_default_projects_modules: "وحدات التمكين الافتراضية للمشاريع الجديدة"
setting_default_projects_public: "هناك مشاريع جديدة عامة بشكل افتراضي"
@@ -3086,6 +3107,12 @@ ar:
setting_feeds_limit: "حد محتوى تغذية"
setting_file_max_size_displayed: "عرض الحد الأقصى لحجم الملفات النصية المضمنة في السطر"
setting_host_name: "إسم المضيف"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3094,7 +3121,7 @@ ar:
In work-based mode, % Complete is calculated from how much work is done in relation to total work. In status-based mode, each status has a % Complete value associated with it. Changing status will change % Complete.
setting_work_package_properties: "خصائص مجموعة العمل"
setting_work_package_startdate_is_adddate: "استخدام التاريخ الحالي كتاريخ البدء لمجموعات العمل الجديدة"
- setting_work_packages_projects_export_limit: "Work packages / Projects export limit"
+ setting_work_packages_projects_export_limit: "حد تصدير حزم العمل / المشاريع"
setting_journal_aggregation_time_minutes: "User actions aggregated within"
setting_log_requesting_user: "تسجيل الدخول تسجيل دخول المستخدم واسم وعنوان البريد لجميع الطلبات"
setting_login_required: "مطلوب مصادقة"
@@ -3191,7 +3218,7 @@ ar:
type: "Entire row by Type"
priority: "Entire row by Priority"
icalendar:
- enable_subscriptions_text_html: Allows users with the necessary permissions to subscribe to OpenProject calendars and access work package information via an external calendar client. Note: Please read about iCalendar subscriptions to understand potential security risks before enabling this.
+ enable_subscriptions_text_html: يتيح للمستخدمين الذين لديهم الأذونات اللازمة الاشتراك في تقاويم OpenProject والوصول إلى معلومات حزم العمل عبر عميل تقويم خارجي. ملاحظة: يرجى قراءة اشتراكات iCalendar لفهم المخاطر الأمنية المحتملة قبل تفعيل هذه الميزة.
language_name_being_default: "%{language_name} (default)"
notifications:
events_explanation: "Governs for which event an email is sent out. Work packages are excluded from this list as the notifications for them can be configured specifically for every user."
@@ -3259,9 +3286,9 @@ ar:
text_custom_field_hint_activate_per_project_and_type: >
Custom fields need to be activated per work package type and per project.
text_wp_status_read_only_html: >
- The Enterprise edition will add these additional add-ons for work packages' statuses fields:
Allow to mark work packages to read-only for specific statuses
+ ستضيف النسخة المؤسسية هذه الإضافات الإضافية لحقول حالات حزم العمل:
السماح بوضع حزم العمل في وضع القراءة فقط لحالات محددة
text_project_custom_field_html: >
- The Enterprise edition will add these additional add-ons for projects' custom fields:
Add custom fields for projects to your Project list to create a project portfolio view
+ ستضيف النسخة المؤسسية هذه الإضافات الإضافية للحقول المخصصة للمشاريع:
إضافة حقول مخصصة للمشاريع إلى قائمة مشروعك لإنشاء عرض محفظة المشاريع
text_custom_logo_instructions: >
A white logo on transparent background is recommended. For best results on both, conventional and retina displays, make sure your image's dimensions are 460px by 60px.
text_custom_export_logo_instructions: >
@@ -3449,14 +3476,14 @@ ar:
warning_user_limit_reached_admin: >
Adding additional users will exceed the current limit. Please upgrade your plan to be able to ensure external users are able to access this instance.
warning_user_limit_reached_instructions: >
- You reached your user limit (%{current}/%{max} active users). Please contact sales@openproject.com to upgrade your Enterprise edition plan and add additional users.
+ لقد وصلت إلى حد المستخدمين الخاص بك (%{current}/%{max} مستخدمين نشطين). يرجى الاتصال بـ sales@openproject.com لترقية خطة النسخة المؤسسية الخاصة بك وإضافة مستخدمين إضافيين.
warning_protocol_mismatch_html: >
warning_bar:
https_mismatch:
- title: "HTTPS mode setup mismatch"
+ title: "عدم تطابق إعداد وضع HTTPS\n"
text_html: >
- Your application is running with HTTPS mode set to %{set_protocol}, but the request is an %{actual_protocol} request. This will result in errors! You will need to set the following configuration value: %{setting_value}. Please see the installation documentation on how to set this configuration.
+ تطبيقك يعمل بوضع HTTPS مضبوط إلى %{set_protocol}، ولكن الطلب هو طلب %{actual_protocol}. سيؤدي ذلك إلى حدوث أخطاء! ستحتاج إلى تعيين قيمة الإعداد التالية: %{setting_value}. يرجى الاطلاع على وثائق التثبيت لمعرفة كيفية تعيين هذا الإعداد.
hostname_mismatch:
title: "Hostname setting mismatch"
text_html: >
@@ -3506,8 +3533,8 @@ ar:
view_description: "Can view this work package."
remove: "إزالة"
share: "شارك"
- text_empty_search_description: "There are no users with the current filter criteria."
- text_empty_search_header: "We couldn't find any matching results."
+ text_empty_search_description: "لا يوجد مستخدمون بالمعايير الحالية للتصفية."
+ text_empty_search_header: "لم نتمكن من العثور على أي نتائج مطابقة."
text_empty_state_description: "The work package has not been shared with anyone yet."
text_empty_state_header: "غير مشترك"
text_user_limit_reached: "Adding additional users will exceed the current limit. Please contact an administrator to increase the user limit to ensure external users are able to access this work package."
@@ -3517,7 +3544,7 @@ ar:
warning_user_limit_reached_admin: >
Adding additional users will exceed the current limit. Please upgrade your plan to be able to ensure external users are able to access this work package.
warning_no_selected_user: "Please select users to share this work package with"
- warning_locked_user: "The user %{user} is locked and cannot be shared with"
+ warning_locked_user: "المستخدم %{user} مقفل ولا يمكن مشاركته"
user_details:
locked: "Locked user"
invited: "Invite sent. "
@@ -3531,12 +3558,12 @@ ar:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
@@ -3560,7 +3587,7 @@ ar:
code_429: "Too many requests. Please try again later."
code_500: "حدث خطأ داخلي."
code_500_outbound_request_failure: "An outbound request to another resource has failed with status code %{status_code}."
- code_500_missing_enterprise_token: "The request can not be handled due to invalid or missing Enterprise token."
+ code_500_missing_enterprise_token: "لا يمكن معالجة الطلب بسبب أن رمز المؤسسة غير صالح أو مفقود."
not_found:
work_package: "The work package you are looking for cannot be found or has been deleted."
expected:
@@ -3745,8 +3772,8 @@ ar:
you: you
link: link
plugin_openproject_auth_plugins:
- name: "OpenProject Auth Plugins"
+ name: "إضافات OpenProject Auth"
description: "Integration of OmniAuth strategy providers for authentication in OpenProject."
plugin_openproject_auth_saml:
- name: "OmniAuth SAML / Single-Sign On"
- description: "Adds the OmniAuth SAML provider to OpenProject"
+ name: "OmniAuth SAML / تسجيل الدخول الموحد"
+ description: "يضيف مزود OmniAuth SAML إلى OpenProject"
diff --git a/config/locales/crowdin/az.yml b/config/locales/crowdin/az.yml
index 75842bb923d7..59a7c4513c26 100644
--- a/config/locales/crowdin/az.yml
+++ b/config/locales/crowdin/az.yml
@@ -300,6 +300,12 @@ az:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: There are currently no types available.
form:
@@ -448,12 +454,20 @@ az:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: There are currently no work package statuses.
no_results_content_text: Add a new status
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -623,6 +637,7 @@ az:
status:
is_closed: "Work package closed"
is_readonly: "Work package read-only"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Notes"
member:
@@ -959,6 +974,14 @@ az:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1143,18 +1166,6 @@ az:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Changesets"
message: "Forums"
@@ -1605,6 +1616,12 @@ az:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1658,7 +1675,7 @@ az:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1675,8 +1692,9 @@ az:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2333,7 +2351,7 @@ az:
label_workflow: "Workflow"
label_workflow_plural: "Workflows"
label_workflow_summary: "Summary"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 closed"
other: "%{count} closed"
@@ -2933,6 +2951,9 @@ az:
setting_cross_project_work_package_relations: "Allow cross-project work package relations"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "Date"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Default language"
setting_default_projects_modules: "Default enabled modules for new projects"
setting_default_projects_public: "New projects are public by default"
@@ -2948,6 +2969,12 @@ az:
setting_feeds_limit: "Feed content limit"
setting_file_max_size_displayed: "Max size of text files displayed inline"
setting_host_name: "Host name"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3389,12 +3416,12 @@ az:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/be.yml b/config/locales/crowdin/be.yml
index 79a8376ff615..3dd437f3e326 100644
--- a/config/locales/crowdin/be.yml
+++ b/config/locales/crowdin/be.yml
@@ -300,6 +300,12 @@ be:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: There are currently no types available.
form:
@@ -460,12 +466,20 @@ be:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: There are currently no work package statuses.
no_results_content_text: Add a new status
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -637,6 +651,7 @@ be:
status:
is_closed: "Work package closed"
is_readonly: "Work package read-only"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Notes"
member:
@@ -973,6 +988,14 @@ be:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1173,18 +1196,6 @@ be:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Changesets"
message: "Forums"
@@ -1671,6 +1682,12 @@ be:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1724,7 +1741,7 @@ be:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1741,8 +1758,9 @@ be:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2399,7 +2417,7 @@ be:
label_workflow: "Workflow"
label_workflow_plural: "Workflows"
label_workflow_summary: "Summary"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 closed"
other: "%{count} closed"
@@ -3003,6 +3021,9 @@ be:
setting_cross_project_work_package_relations: "Allow cross-project work package relations"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "Дата"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Default language"
setting_default_projects_modules: "Default enabled modules for new projects"
setting_default_projects_public: "New projects are public by default"
@@ -3018,6 +3039,12 @@ be:
setting_feeds_limit: "Feed content limit"
setting_file_max_size_displayed: "Max size of text files displayed inline"
setting_host_name: "Host name"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3461,12 +3488,12 @@ be:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/bg.yml b/config/locales/crowdin/bg.yml
index b85fe833b422..2f34ed109ddc 100644
--- a/config/locales/crowdin/bg.yml
+++ b/config/locales/crowdin/bg.yml
@@ -300,6 +300,12 @@ bg:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: В момента има няма типове на разположение.
form:
@@ -448,12 +454,20 @@ bg:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: Има в момента няма статуси за работни пакети.
no_results_content_text: Добавяне на ново състояние
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -623,6 +637,7 @@ bg:
status:
is_closed: "Работният пакет е затворен"
is_readonly: "Work package read-only"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Бележки"
member:
@@ -959,6 +974,14 @@ bg:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1143,18 +1166,6 @@ bg:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Набори от промени"
message: "Форуми"
@@ -1605,6 +1616,12 @@ bg:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1658,7 +1675,7 @@ bg:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1675,8 +1692,9 @@ bg:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2333,7 +2351,7 @@ bg:
label_workflow: "Работен поток"
label_workflow_plural: "Работни потоци"
label_workflow_summary: "Обобщение"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 затворен"
other: "%{count} затворено"
@@ -2933,6 +2951,9 @@ bg:
setting_cross_project_work_package_relations: "Allow cross-project work package relations"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "Дата"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Език по подразбиране"
setting_default_projects_modules: "Default enabled modules for new projects"
setting_default_projects_public: "New projects are public by default"
@@ -2948,6 +2969,12 @@ bg:
setting_feeds_limit: "Feed content limit"
setting_file_max_size_displayed: "Max size of text files displayed inline"
setting_host_name: "Име на хост"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Имейлът за активиране изтича след"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3389,12 +3416,12 @@ bg:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/ca.yml b/config/locales/crowdin/ca.yml
index 783266cce851..c1f5e59cf3c3 100644
--- a/config/locales/crowdin/ca.yml
+++ b/config/locales/crowdin/ca.yml
@@ -297,6 +297,12 @@ ca:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Actualment no hi ha cap classe disponible.
form:
@@ -445,12 +451,20 @@ ca:
No es poden canviar els atributs amb l'excepció de l'atribut estat-
Nota : Els valors heretats (p.e., de fills o relacions) es continuaran aplicant.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Clica per a assignar o canviar el color d'aquest estat.
Es mostra al botó d'estat i es pot fer servir per a destacar paquets de treball a la taula.
index:
no_results_title_text: Actualment no hi ha cap estat de paquet de treball.
no_results_content_text: Afegir un nou estat
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Clar"
light_high_contrast: "Clar alt contrast"
@@ -619,6 +633,7 @@ ca:
status:
is_closed: "Paquet de treball tancat"
is_readonly: "Paquet de treball en sols lectura"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Notes"
member:
@@ -955,6 +970,14 @@ ca:
base:
working_days_are_missing: "Almenys un dia de la setmana s'ha de definir com a dia laborable."
previous_working_day_changes_unprocessed: "Els canvis anteriors a la configuració de dies laborals encara no s'han aplicat."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1139,18 +1162,6 @@ ca:
other: "%{count} hores"
updated: "canviat de %{old_value} a %{value}"
logged_for: "Registrat per"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "eliminat"
- updated: "canviat de %{old_value} a %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordenat"
- work_package:
- updated: "canviat de %{old_value} a %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Conjunt de canvis"
message: "Fòrums"
@@ -1601,6 +1612,12 @@ ca:
pdf_gantt: "PDF Gantt"
image:
omitted: "Imatge no exportada."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1654,7 +1671,7 @@ ca:
dates_changed: "Les dates han canviat"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: per canvis en el predecessor %{link}
@@ -1671,8 +1688,9 @@ ca:
working: "%{date} és ara laboral"
non_working: "%{date} és ara no laboral"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2329,7 +2347,7 @@ ca:
label_workflow: "Flux de treball"
label_workflow_plural: "Fluxos de treball"
label_workflow_summary: "Resum"
- label_working_days: "Dies laborals"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "Un tancat"
other: "%{count} tancats"
@@ -2922,6 +2940,9 @@ ca:
setting_cross_project_work_package_relations: "Permetre les relacions creuades entre projectes pels paquets de treball"
setting_first_week_of_year: "La primera setmana de l'any conté"
setting_date_format: "Data"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Idioma per defecte"
setting_default_projects_modules: "Mòduls activats per defecte en els projectes nous"
setting_default_projects_public: "Els projectes nous són públics per defecte"
@@ -2937,6 +2958,12 @@ ca:
setting_feeds_limit: "Límit de contingut del canals"
setting_file_max_size_displayed: "Mida màxima dels fitxers de text mostrats en línia"
setting_host_name: "Nom del servidor"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "L'activació de correu electrònic caduca després de"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3378,12 +3405,12 @@ ca:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Els dies que no estan seleccionats s'ometen en planificar paquets de treball (i no inclosos en contar els dies). Aquests poden ser substituïts directament als paquets de treball.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Les dates afegides a la llista de sota són considerades com a no laborals i omeses en programar paquets de treball.
change_button: "Canvia els dies laborals"
warning: >
- Canviar quins dies de la setmana es consideren laborables i quins no pot afectar les dates d'inici i final de tots els paquets de treball en tots els projectes d'aquesta instància. Si us plau, tingues en compte que els canvis només s'apliquen després de fer clic al botó d'aplicar els canvis.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Dies laborals"" han canviat (%{changes})._
days:
diff --git a/config/locales/crowdin/ckb-IR.yml b/config/locales/crowdin/ckb-IR.yml
index 6b620b9c520d..18fd56d616ba 100644
--- a/config/locales/crowdin/ckb-IR.yml
+++ b/config/locales/crowdin/ckb-IR.yml
@@ -300,6 +300,12 @@ ckb-IR:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: There are currently no types available.
form:
@@ -448,12 +454,20 @@ ckb-IR:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: There are currently no work package statuses.
no_results_content_text: Add a new status
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -623,6 +637,7 @@ ckb-IR:
status:
is_closed: "Work package closed"
is_readonly: "Work package read-only"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Notes"
member:
@@ -959,6 +974,14 @@ ckb-IR:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1143,18 +1166,6 @@ ckb-IR:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Changesets"
message: "Forums"
@@ -1605,6 +1616,12 @@ ckb-IR:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1658,7 +1675,7 @@ ckb-IR:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1675,8 +1692,9 @@ ckb-IR:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2333,7 +2351,7 @@ ckb-IR:
label_workflow: "Workflow"
label_workflow_plural: "Workflows"
label_workflow_summary: "Summary"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 closed"
other: "%{count} closed"
@@ -2933,6 +2951,9 @@ ckb-IR:
setting_cross_project_work_package_relations: "Allow cross-project work package relations"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "Date"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Default language"
setting_default_projects_modules: "Default enabled modules for new projects"
setting_default_projects_public: "New projects are public by default"
@@ -2948,6 +2969,12 @@ ckb-IR:
setting_feeds_limit: "Feed content limit"
setting_file_max_size_displayed: "Max size of text files displayed inline"
setting_host_name: "Host name"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3389,12 +3416,12 @@ ckb-IR:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/cs.yml b/config/locales/crowdin/cs.yml
index a727e795bcb2..86bc449dc686 100644
--- a/config/locales/crowdin/cs.yml
+++ b/config/locales/crowdin/cs.yml
@@ -300,6 +300,12 @@ cs:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: V současné době nejsou k dispozici žádné typy.
form:
@@ -460,12 +466,20 @@ cs:
Žádné atributy nelze změnit s výjimkou stavu samotného.
Poznámka: zděděné hodnoty (např. z potomků či dalších vztahů) budou platné i nadále.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Klikněte na přiřadit nebo změnit barvu této priority.
lze použít ke zvýraznění pracovních balíčků v tabulce.
index:
no_results_title_text: Momentálně zde nejsou žádné stavy pracovního balíčku.
no_results_content_text: Přidat nový stav
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Světlý"
light_high_contrast: "Světlý kontrast"
@@ -637,6 +651,7 @@ cs:
status:
is_closed: "Pracovní balíček uzavřen"
is_readonly: "Pracovní balíček jen pro čtení"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Poznámky"
member:
@@ -973,6 +988,14 @@ cs:
base:
working_days_are_missing: "Nejméně jeden den v týdnu musí být definován jako pracovní den."
previous_working_day_changes_unprocessed: "Předchozí změny nastavení pracovních dnů ještě nebyly použity."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1173,18 +1196,6 @@ cs:
other: "%{count} hodiny"
updated: "změněno z %{old_value} na %{value}"
logged_for: "Přihlášen "
- meeting_agenda_item:
- duration:
- added: "nastavit na %{value}"
- added_html: "nastavit na %{value}"
- removed: "odstraněno"
- updated: "změněno z %{old_value} na %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "změněno z %{old_value} na %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Změny"
message: "Fóra"
@@ -1671,6 +1682,12 @@ cs:
pdf_gantt: "PDF Gantt"
image:
omitted: "Obrázek nebyl exportován."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1724,7 +1741,7 @@ cs:
dates_changed: "Data změněna"
default_attribute_written: "Zápis atributů pouze pro čtení"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "Aktualizace systému OpenProject:"
cause_descriptions:
work_package_predecessor_changed_times: podle změn na předchůdce %{link}
@@ -1741,8 +1758,9 @@ cs:
working: "%{date} je pracovní "
non_working: "%{date} je nepracovní "
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
Od této chvíle se zde v záložce Aktivita zobrazí činnost související s odkazy na soubory (soubory uložené v externím úložišti). Níže uvedené představují činnost týkající se již existujících:
@@ -2399,7 +2417,7 @@ cs:
label_workflow: "Pracovní postup"
label_workflow_plural: "Pracovní postupy"
label_workflow_summary: "Souhrn"
- label_working_days: "Pracovní dny"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 uzavřeno"
other: "%{count} uzavřených"
@@ -3002,6 +3020,9 @@ cs:
setting_cross_project_work_package_relations: "Povolit vztahy mezi projekty a pracovními balíčky"
setting_first_week_of_year: "První týden v roce obsahuje"
setting_date_format: "Datum"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Výchozí jazyk"
setting_default_projects_modules: "Výchozí zapnutné moduly pro nový projekt"
setting_default_projects_public: "Nové projekty nastavovat jako veřejné"
@@ -3017,6 +3038,12 @@ cs:
setting_feeds_limit: "Limit obsahu kanálů"
setting_file_max_size_displayed: "Maximální velikost textových souborů zobrazených přímo na stránce"
setting_host_name: "Název serveru"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Platnost aktivačního e-mailu vyprší po"
setting_work_package_done_ratio: "Výpočet průběhu"
setting_work_package_done_ratio_field: "Work-based"
@@ -3459,12 +3486,12 @@ cs:
additional_privileges_project_or_group: "Může mít dodatečná oprávnění (jako člen skupiny)"
working_days:
info: >
- Nevybrané dny jsou při plánování pracovních balíčků přeskočeny (a nejsou zahrnuty ve denním počtu). Ty mohou být přepsány na úrovni pracovního balíčku.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Data přidaná do níže uvedeného seznamu jsou považována za nefunkční a při plánování pracovních balíčků přeskočena.
change_button: "Změnit pracovní dny"
warning: >
- Změna, které dny v týdnu jsou považovány za pracovní dny nebo za nepracovní dny, může ovlivnit začátek a ukončení všech pracovních balíčků ve všech projektech v tomto případě. Vezměte prosím na vědomí, že změny jsou aplikovány až po kliknutí na tlačítko změn.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Pracovní dny** změněny (%{changes})._
days:
diff --git a/config/locales/crowdin/da.yml b/config/locales/crowdin/da.yml
index 5356c1267fea..681cd6ef54bc 100644
--- a/config/locales/crowdin/da.yml
+++ b/config/locales/crowdin/da.yml
@@ -298,6 +298,12 @@ da:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Der er i øjeblikket ingen tilgængelige typer.
form:
@@ -446,12 +452,20 @@ da:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: There are currently no work package statuses.
no_results_content_text: Add a new status
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -621,6 +635,7 @@ da:
status:
is_closed: "Lukket arbejdspakke"
is_readonly: "Work package read-only"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Kommentarer"
member:
@@ -957,6 +972,14 @@ da:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1141,18 +1164,6 @@ da:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Pakker af ændringer"
message: "Fora"
@@ -1603,6 +1614,12 @@ da:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1656,7 +1673,7 @@ da:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1673,8 +1690,9 @@ da:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2331,7 +2349,7 @@ da:
label_workflow: "Arbejdsgang"
label_workflow_plural: "Arbejdsprocesser"
label_workflow_summary: "Opsummering"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 lukket"
other: "%{count} lukkede"
@@ -2929,6 +2947,9 @@ da:
setting_cross_project_work_package_relations: "Tillad forbindelser mellem arbejdspakker på tværs af projekter"
setting_first_week_of_year: "Første uge i året indeholder"
setting_date_format: "Dato"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Forhåndsvalgt sprog"
setting_default_projects_modules: "Forhåndsvalgt aktive moduler for nye projekter"
setting_default_projects_public: "Nye projekter er på forhånd sat som offentlige"
@@ -2944,6 +2965,12 @@ da:
setting_feeds_limit: "Grænse for indhold af feeds"
setting_file_max_size_displayed: "Maksimal størrelse af tekstfiler, der vises inline"
setting_host_name: "Værtsnavn"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3385,12 +3412,12 @@ da:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/de.yml b/config/locales/crowdin/de.yml
index 677c1a75ad72..414aa2761dac 100644
--- a/config/locales/crowdin/de.yml
+++ b/config/locales/crowdin/de.yml
@@ -297,6 +297,12 @@ de:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Derzeit stehen keine Typen zur Verfügung.
form:
@@ -444,11 +450,19 @@ de:
Außer dem Status selbst können dann keine Attribute verändert werden.
Hinweis: Vererbte Attribute (z.B. von Kinderelementen oder Relationen) werden auch auf Arbeitspakete in diesen Status angewandt.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Klicken zum Zuweisen einer Farbe für diesen Status. Diese wird für die Hervorhebung von Arbeitspaketen in Tabellen verwendet.
index:
no_results_title_text: Derzeit gibt es keine Arbeitspaket-Status.
no_results_content_text: Neuen Status hinzufügen
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Hell"
light_high_contrast: "Hell (hoher Kontrast)"
@@ -618,6 +632,7 @@ de:
status:
is_closed: "Arbeitspaket geschlossen"
is_readonly: "Arbeitspakete schreibgeschützt"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Kommentare"
member:
@@ -954,6 +969,14 @@ de:
base:
working_days_are_missing: "Mindestens ein Wochentag muss als Arbeitstag definiert werden."
previous_working_day_changes_unprocessed: "Die vorherigen Änderungen an der Konfiguration der Arbeitstage wurden noch nicht angewendet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1138,18 +1161,6 @@ de:
other: "%{count} Stunden"
updated: "geändert von %{old_value} zu %{value}"
logged_for: "Gebucht für"
- meeting_agenda_item:
- duration:
- added: "auf %{value} eingestellt"
- added_html: "auf %{value} eingestellt"
- removed: "entfernt"
- updated: "von %{old_value} zu %{value} geändert"
- updated_html: "von %{old_value} zu %{value} geändert"
- position:
- updated: "neu geordnet"
- work_package:
- updated: "von %{old_value} zu %{value} geändert"
- updated_html: "von %{old_value} zu %{value} geändert"
filter:
changeset: "Änderungssätze"
message: "Foren"
@@ -1600,6 +1611,12 @@ de:
pdf_gantt: "PDF Gantt"
image:
omitted: "Bild nicht exportiert."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1653,7 +1670,7 @@ de:
dates_changed: "Datum geändert"
default_attribute_written: "Nur-Lese-Attribute wurde geschrieben"
progress_mode_changed_to_status_based: "Fortschrittsberechnung aktualisiert"
- status_p_complete_changed: "Status % abgeschlossen geändert"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject-Systemaktualisierung:"
cause_descriptions:
work_package_predecessor_changed_times: durch Änderungen am Vorgänger %{link}
@@ -1670,8 +1687,9 @@ de:
working: "%{date} ist jetzt ein Arbeitstag"
non_working: "%{date} ist jetzt ein arbeitsfreier Tag"
progress_mode_changed_to_status_based: Fortschrittberechnung wurde auf Status-basiert gesetzt
- status_p_complete_changed: >-
- % Abgeschlossen für Status '%{status_name}' geändert von %{old_value}% auf %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
Ab sofort erscheinen hier Aktivitäten, die sich auf Datei-Links beziehen (Dateien in externen Speichermedien) auf der Registerkarte Aktivität. Folgende Aktivitäten betreffen bereits existierende Links:
@@ -2328,7 +2346,7 @@ de:
label_workflow: "Workflow"
label_workflow_plural: "Workflows"
label_workflow_summary: "Zusammenfassung"
- label_working_days: "Werktage"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 geschlossen"
other: "%{count} geschlossen"
@@ -2928,6 +2946,9 @@ de:
setting_cross_project_work_package_relations: "Arbeitspaket-Beziehungen zwischen Projekten erlauben"
setting_first_week_of_year: "Die erste Woche im Jahr enthält"
setting_date_format: "Datum"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Standard-Sprache"
setting_default_projects_modules: "Standardmäßig aktivierte Module für neue Projekte"
setting_default_projects_public: "Neue Projekte sind standardmäßig öffentlich"
@@ -2943,6 +2964,12 @@ de:
setting_feeds_limit: "Max. Anzahl Einträge pro Atom-Feed"
setting_file_max_size_displayed: "Maximale Größe inline angezeigter Textdateien"
setting_host_name: "Hostname"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Aktivierungs-Mail läuft ab nach"
setting_work_package_done_ratio: "Fortschrittsberechnung"
setting_work_package_done_ratio_field: "Arbeitsbezogen"
@@ -3383,12 +3410,12 @@ de:
additional_privileges_project_or_group: "hat möglicherweise zusätzliche Berechtigungen (als Projekt- oder Gruppenmitglied)"
working_days:
info: >
- Tage, die nicht ausgewählt sind, werden bei der Planung von Arbeitspaketen übersprungen (und bei der Tageszählung nicht berücksichtigt). Diese können auf Arbeitspaket-Ebene überschrieben werden.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Daten, die der Liste unten hinzugefügt werden, gelten als arbeitsfrei und werden bei der Planung von Arbeitspaketen übersprungen.
change_button: "Arbeitstage ändern"
warning: >
- Die Änderung der Wochentage, die als Arbeitstage oder arbeitsfreie Tage gelten, kann sich in diesem Fall auf die Start- und Endtage aller Arbeitspakete in allen Projekten auswirken. Bitte beachten Sie, dass die Änderungen erst wirksam werden, nachdem Sie auf die Schaltfläche Änderungen anwenden geklickt haben.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Arbeitstage** geändert (%{changes})._
days:
diff --git a/config/locales/crowdin/el.yml b/config/locales/crowdin/el.yml
index e3006614f8d7..6044e7949c54 100644
--- a/config/locales/crowdin/el.yml
+++ b/config/locales/crowdin/el.yml
@@ -296,6 +296,12 @@ el:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Προς το παρόν δεν υπάρχουν διαθέσιμοι τύποι.
form:
@@ -444,12 +450,20 @@ el:
Δεν θα είναι δυνατή η αλλαγή ιδιοτήτων εκτός από την κατάσταση.
Σημείωση: Μεταβιβαζόμενες τιμές (π.χ., από τα παιδιά ή σχέσεις) θα εξακολουθούν να ισχύουν.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Κάντε κλικ για να αντιστοιχίσετε ή να αλλάξετε το χρώμα αυτής της κατάστασης.
Εμφανίζεται στο κουμπί κατάστασης και μπορεί να χρησιμοποιηθεί για την επισήμανση πακέτων εργασίας στον πίνακα.
index:
no_results_title_text: Προς το παρόν δεν υπάρχουν καταστάσεις για το πακέτο εργασίας.
no_results_content_text: Προσθέσετε μια νέα κατάσταση
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -619,6 +633,7 @@ el:
status:
is_closed: "Το πακέτο εργασίας είναι κλειστό"
is_readonly: "Εργασία μόνο για ανάγνωση"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Παρατηρήσεις"
member:
@@ -955,6 +970,14 @@ el:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1139,18 +1162,6 @@ el:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Σύνολα Αλλαγών"
message: "Φόρουμ"
@@ -1601,6 +1612,12 @@ el:
pdf_gantt: "PDF Gantt"
image:
omitted: "Η εικόνα δεν εξήχθη."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1654,7 +1671,7 @@ el:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1671,8 +1688,9 @@ el:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2329,7 +2347,7 @@ el:
label_workflow: "Ροή εργασιών"
label_workflow_plural: "Ροές εργασίας"
label_workflow_summary: "Περίληψη"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 κλειστό"
other: "%{count} κλειστά"
@@ -2928,6 +2946,9 @@ el:
setting_cross_project_work_package_relations: "Επιτρέψτε συσχετισμό πακέτων εργασίας μεταξύ έργων"
setting_first_week_of_year: "Η πρώτη εβδομάδα του έτους περιέχει"
setting_date_format: "Ημερομηνία"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Προεπιλεγμένη γλώσσα"
setting_default_projects_modules: "Ενότητα ενεργοποιημένες από προεπιλογή για τα νέα έργα"
setting_default_projects_public: "Τα νέα έργα είναι δημόσια από προεπιλογή"
@@ -2943,6 +2964,12 @@ el:
setting_feeds_limit: "Όριο συγκατάθεσης τροφοδοσίας"
setting_file_max_size_displayed: "Μέγιστο μέγεθος αρχείων κειμένου που εμφανίζονται inline"
setting_host_name: "Όνομα εξυπηρετητή"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Το μήνυμα ενεργοποίησης λήγει μετά από"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3383,12 +3410,12 @@ el:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/eo.yml b/config/locales/crowdin/eo.yml
index 6daebb0d03c9..a889bf65cac6 100644
--- a/config/locales/crowdin/eo.yml
+++ b/config/locales/crowdin/eo.yml
@@ -300,6 +300,12 @@ eo:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: There are currently no types available.
form:
@@ -448,12 +454,20 @@ eo:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: There are currently no work package statuses.
no_results_content_text: Aldoni novan staton
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -623,6 +637,7 @@ eo:
status:
is_closed: "Laborpakaĵo fermita"
is_readonly: "Nurlega laborpakaĵo"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Notoj"
member:
@@ -959,6 +974,14 @@ eo:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1143,18 +1166,6 @@ eo:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Ŝanĝaroj"
message: "Forumoj"
@@ -1605,6 +1616,12 @@ eo:
pdf_gantt: "PDF Gantt"
image:
omitted: "Bildo ne eksportita."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1658,7 +1675,7 @@ eo:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1675,8 +1692,9 @@ eo:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2333,7 +2351,7 @@ eo:
label_workflow: "Laborfluo"
label_workflow_plural: "Laborfluoj"
label_workflow_summary: "Resumo"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 fermita"
other: "%{count} fermitaj"
@@ -2933,6 +2951,9 @@ eo:
setting_cross_project_work_package_relations: "Allow cross-project work package relations"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "Dato"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Default language"
setting_default_projects_modules: "Default enabled modules for new projects"
setting_default_projects_public: "New projects are public by default"
@@ -2948,6 +2969,12 @@ eo:
setting_feeds_limit: "Feed content limit"
setting_file_max_size_displayed: "Max size of text files displayed inline"
setting_host_name: "Host name"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3389,12 +3416,12 @@ eo:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/es.yml b/config/locales/crowdin/es.yml
index 66366d7202ff..ceeb050ec753 100644
--- a/config/locales/crowdin/es.yml
+++ b/config/locales/crowdin/es.yml
@@ -297,6 +297,12 @@ es:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Actualmente no hay tipos disponibles.
form:
@@ -445,12 +451,20 @@ es:
Excepto el estado, ningún otro atributo se puede modificar.
Nota: Los valores heredados (por ejemplo, de elementos secundarios o relaciones) seguirán aplicándose.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Haga clic para asignar o cambiar el color de este estado.
Se muestra en el botón de estado y puede usarse para resaltar paquetes de trabajo en la tabla.
index:
no_results_title_text: Actualmente no hay estados de paquetes de trabajo.
no_results_content_text: Añadir un nuevo estado
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Claro"
light_high_contrast: "Contraste alto claro"
@@ -620,6 +634,7 @@ es:
status:
is_closed: "Paquete de trabajo cerrado"
is_readonly: "Paquete de trabajo de solo lectura"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Notas"
member:
@@ -730,7 +745,7 @@ es:
parent_issue: "Padre"
parent_work_package: "Padre"
priority: "Prioridad"
- progress: "% Compleado"
+ progress: "% Completado"
readonly: "Solo lectura"
remaining_hours: "Trabajo restante"
remaining_time: "Trabajo restante"
@@ -956,6 +971,14 @@ es:
base:
working_days_are_missing: "Al menos un día de la semana debe definirse como laboral."
previous_working_day_changes_unprocessed: "Los cambios anteriores en la configuración de días laborables no se han aplicado aún."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1140,18 +1163,6 @@ es:
other: "%{count} horas"
updated: "cambiado de %{old_value} a %{value}"
logged_for: "Registrado para"
- meeting_agenda_item:
- duration:
- added: "fijado en %{value}"
- added_html: "fijado en %{value}"
- removed: "eliminado"
- updated: "cambiado de %{old_value} a %{value}"
- updated_html: "cambiado de %{old_value} a %{value}"
- position:
- updated: "reordenado"
- work_package:
- updated: "cambiado de %{old_value} a %{value}"
- updated_html: "cambiado de %{old_value} a %{value}"
filter:
changeset: "Conjuntos de cambios"
message: "Foros"
@@ -1602,6 +1613,12 @@ es:
pdf_gantt: "PDF Gantt"
image:
omitted: "Imagen no exportada."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1655,7 +1672,7 @@ es:
dates_changed: "Cambio de fechas"
default_attribute_written: "Atributos de solo lectura escritos"
progress_mode_changed_to_status_based: "Cálculo del progreso actualizado"
- status_p_complete_changed: "Estado % completado cambiado"
+ status_changed: "Status '%{status_name}'"
system_update: "Actualización del sistema OpenProject:"
cause_descriptions:
work_package_predecessor_changed_times: por cambios al %{link} predecesor
@@ -1672,8 +1689,9 @@ es:
working: "%{date} es ahora laboral"
non_working: "%{date} es ahora no laboral"
progress_mode_changed_to_status_based: Modo de cálculo del progreso establecido como basado en el estado
- status_p_complete_changed: >-
- Valor de % completado para el estado «%{status_name}» cambiado de %{old_value} % a %{new_value} %
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
A partir de ahora, la actividad relacionada con los enlaces de archivos (archivos almacenados en almacenamiento externo) aparecerá aquí en la pestaña Actividad. La siguiente representa la actividad relativa a los enlaces que ya existían:
@@ -2330,7 +2348,7 @@ es:
label_workflow: "Flujo de trabajo"
label_workflow_plural: "Flujos de trabajo"
label_workflow_summary: "Resumen"
- label_working_days: "Días laborables"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 cerrado"
other: "%{count} cerrados"
@@ -2929,6 +2947,9 @@ es:
setting_cross_project_work_package_relations: "Permitir relaciones cruzadas en paquetes de trabajo de proyecto"
setting_first_week_of_year: "La primera semana del año contiene"
setting_date_format: "Fecha"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Idioma predeterminado"
setting_default_projects_modules: "Modulos activados por defecto para nuevos proyectos"
setting_default_projects_public: "Nuevos proyectos son públicos por defecto"
@@ -2944,6 +2965,12 @@ es:
setting_feeds_limit: "Limite de contenido de feed"
setting_file_max_size_displayed: "Tamaño máximo de archivos de texto mostrado en linea"
setting_host_name: "Nombre de host"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "El correo electrónico de activación caduca después de"
setting_work_package_done_ratio: "Cálculo del progreso"
setting_work_package_done_ratio_field: "Basado en el trabajo"
@@ -3384,12 +3411,12 @@ es:
additional_privileges_project_or_group: "Puede tener privilegios adicionales (como miembros del proyecto o de un grupo)"
working_days:
info: >
- Los días no seleccionados se omiten al programar los paquetes de trabajo (y no se incluyen en el recuento de días). Esto puede anularse a nivel de paquete de trabajo.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Las fechas añadidas a la lista siguiente se consideran no laborables y se omiten al programar los paquetes de trabajo.
change_button: "Cambiar los días laborables"
warning: >
- Cambiar qué días de la semana se consideran días laborables o no laborables puede afectar a las fechas de inicio y fin de todos los paquetes de trabajo en todos los proyectos de esta instancia. Tenga en cuenta que los cambios solo se aplican después de hacer clic en el botón aplicar cambios.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Días laborales** cambiados (%{changes})._
days:
diff --git a/config/locales/crowdin/et.yml b/config/locales/crowdin/et.yml
index 25d08a32b7bd..27264a2abd63 100644
--- a/config/locales/crowdin/et.yml
+++ b/config/locales/crowdin/et.yml
@@ -300,6 +300,12 @@ et:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: There are currently no types available.
form:
@@ -448,12 +454,20 @@ et:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: There are currently no work package statuses.
no_results_content_text: Lisa uus staatus
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -623,6 +637,7 @@ et:
status:
is_closed: "Teema on suletud"
is_readonly: "Work package read-only"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Märkmed"
member:
@@ -959,6 +974,14 @@ et:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1143,18 +1166,6 @@ et:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Toimikud"
message: "Foorumid"
@@ -1605,6 +1616,12 @@ et:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1658,7 +1675,7 @@ et:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1675,8 +1692,9 @@ et:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2333,7 +2351,7 @@ et:
label_workflow: "Töövoog"
label_workflow_plural: "Töövood"
label_workflow_summary: "Kokkuvõte"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 suletud"
other: "%{count} suletud"
@@ -2933,6 +2951,9 @@ et:
setting_cross_project_work_package_relations: "Võimalda seostada teemasid teistest projektidest"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "Kuupäev"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Vaikimisi keel"
setting_default_projects_modules: "Uue projekti vaikimisi moodulid"
setting_default_projects_public: "Uued projektid on vaikimisi avalikud"
@@ -2948,6 +2969,12 @@ et:
setting_feeds_limit: "Uudisvoogude suurim uudiste arv"
setting_file_max_size_displayed: "Teksti sees kuvatava tekstifaili maksimaalne suurus"
setting_host_name: "Serveri nimi ja teerada"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3389,12 +3416,12 @@ et:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/eu.yml b/config/locales/crowdin/eu.yml
index bf5116599a2d..5b13cbd6a71e 100644
--- a/config/locales/crowdin/eu.yml
+++ b/config/locales/crowdin/eu.yml
@@ -300,6 +300,12 @@ eu:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: There are currently no types available.
form:
@@ -448,12 +454,20 @@ eu:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: There are currently no work package statuses.
no_results_content_text: Add a new status
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -623,6 +637,7 @@ eu:
status:
is_closed: "Work package closed"
is_readonly: "Work package read-only"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Notes"
member:
@@ -959,6 +974,14 @@ eu:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1143,18 +1166,6 @@ eu:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Changesets"
message: "Forums"
@@ -1605,6 +1616,12 @@ eu:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1658,7 +1675,7 @@ eu:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1675,8 +1692,9 @@ eu:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2333,7 +2351,7 @@ eu:
label_workflow: "Workflow"
label_workflow_plural: "Workflows"
label_workflow_summary: "Summary"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 closed"
other: "%{count} closed"
@@ -2933,6 +2951,9 @@ eu:
setting_cross_project_work_package_relations: "Allow cross-project work package relations"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "Date"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Default language"
setting_default_projects_modules: "Default enabled modules for new projects"
setting_default_projects_public: "New projects are public by default"
@@ -2948,6 +2969,12 @@ eu:
setting_feeds_limit: "Feed content limit"
setting_file_max_size_displayed: "Max size of text files displayed inline"
setting_host_name: "Host name"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3389,12 +3416,12 @@ eu:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/fa.yml b/config/locales/crowdin/fa.yml
index 850f22085a4a..53eea8f5f584 100644
--- a/config/locales/crowdin/fa.yml
+++ b/config/locales/crowdin/fa.yml
@@ -300,6 +300,12 @@ fa:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: There are currently no types available.
form:
@@ -448,12 +454,20 @@ fa:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: There are currently no work package statuses.
no_results_content_text: Add a new status
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -623,6 +637,7 @@ fa:
status:
is_closed: "بسته کاری بسته شد"
is_readonly: "Work package read-only"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "یادداشت ها"
member:
@@ -959,6 +974,14 @@ fa:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1143,18 +1166,6 @@ fa:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Changesets"
message: "Forums"
@@ -1605,6 +1616,12 @@ fa:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1658,7 +1675,7 @@ fa:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1675,8 +1692,9 @@ fa:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2333,7 +2351,7 @@ fa:
label_workflow: "Workflow"
label_workflow_plural: "Workflows"
label_workflow_summary: "Summary"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 closed"
other: "%{count} بسته شده"
@@ -2933,6 +2951,9 @@ fa:
setting_cross_project_work_package_relations: "Allow cross-project work package relations"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "تاریخ"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Default language"
setting_default_projects_modules: "Default enabled modules for new projects"
setting_default_projects_public: "New projects are public by default"
@@ -2948,6 +2969,12 @@ fa:
setting_feeds_limit: "Feed content limit"
setting_file_max_size_displayed: "Max size of text files displayed inline"
setting_host_name: "Host name"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3389,12 +3416,12 @@ fa:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/fi.yml b/config/locales/crowdin/fi.yml
index 2224437beff2..3be7f249e580 100644
--- a/config/locales/crowdin/fi.yml
+++ b/config/locales/crowdin/fi.yml
@@ -300,6 +300,12 @@ fi:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Tällä hetkellä tyyppejä ei ole saatavilla.
form:
@@ -448,12 +454,20 @@ fi:
Attribuutteja ei voi muuttaa lukuunottamatta tilaa.
Huomautus: Perittyjä arvoja (esim. alitehtehtäviltä tai riippuvuuksista) sovelletaan.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: Ei tehtävien tiloja.
no_results_content_text: Lisää uusi tila
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -623,6 +637,7 @@ fi:
status:
is_closed: "Tehtävä suljettu"
is_readonly: "Work package read-only"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Kommentit"
member:
@@ -959,6 +974,14 @@ fi:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1143,18 +1166,6 @@ fi:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Muutosryhmät"
message: "Keskustelupalstat"
@@ -1605,6 +1616,12 @@ fi:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1658,7 +1675,7 @@ fi:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1675,8 +1692,9 @@ fi:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2333,7 +2351,7 @@ fi:
label_workflow: "Työnkulku"
label_workflow_plural: "Työnkulut"
label_workflow_summary: "Yhteenveto"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 suljettu"
other: "%{count} suljettua"
@@ -2933,6 +2951,9 @@ fi:
setting_cross_project_work_package_relations: "Salli projektien väliset tehtävien riippuvuudet"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "Päivämäärä"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Vakiokieli"
setting_default_projects_modules: "Oletusmodulit uusille projketeille"
setting_default_projects_public: "Uudet projektit ovat oletuksena julkisia"
@@ -2948,6 +2969,12 @@ fi:
setting_feeds_limit: "Syötteen sisällön raja"
setting_file_max_size_displayed: "Max size of text files displayed inline"
setting_host_name: "Verkko-osoite"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Sähköpostisi vahvistuslinkki vanhentuu"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3389,12 +3416,12 @@ fi:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/fil.yml b/config/locales/crowdin/fil.yml
index 18859cad341f..bc68eb9eb44e 100644
--- a/config/locales/crowdin/fil.yml
+++ b/config/locales/crowdin/fil.yml
@@ -300,6 +300,12 @@ fil:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Sa kasalukuyan ay walang mga uri na available.
form:
@@ -448,12 +454,20 @@ fil:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: Sa kasalukuyan ay walang mga estado ng work package.
no_results_content_text: Magdagdag ng bagong estado
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -623,6 +637,7 @@ fil:
status:
is_closed: "Sarado na ang pagawaan ng pakete"
is_readonly: "Work package read-only"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Ang mga tala"
member:
@@ -959,6 +974,14 @@ fil:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1143,18 +1166,6 @@ fil:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Changesets"
message: "Mga forum"
@@ -1605,6 +1616,12 @@ fil:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1658,7 +1675,7 @@ fil:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1675,8 +1692,9 @@ fil:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2333,7 +2351,7 @@ fil:
label_workflow: "Daloy ng trabaho"
label_workflow_plural: "Daloy ng trabaho"
label_workflow_summary: "Buod"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "Isa ang isinara"
other: "%{count} ang isinara"
@@ -2931,6 +2949,9 @@ fil:
setting_cross_project_work_package_relations: "Pahintulutan ang cross-project na relasyon ng work package"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "Petsa"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Default na linggwahe"
setting_default_projects_modules: "I-default ang pinaganang mga modyul para sa bagong proyekto"
setting_default_projects_public: "Bagong proyektong ay publiko sa pamamagitan ng default"
@@ -2946,6 +2967,12 @@ fil:
setting_feeds_limit: "Limitasyon ng nilalaman na feed"
setting_file_max_size_displayed: "Max na laki ng mga tekstong file na ipinapakita inline"
setting_host_name: "Host name"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3387,12 +3414,12 @@ fil:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/fr.yml b/config/locales/crowdin/fr.yml
index 349885ce9001..9eceeabf752f 100644
--- a/config/locales/crowdin/fr.yml
+++ b/config/locales/crowdin/fr.yml
@@ -300,6 +300,12 @@ fr:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Il n'y a actuellement aucun type disponible.
form:
@@ -448,12 +454,20 @@ fr:
Aucuns attributs ne peut être changés à l’exception de l’État.
Note: les valeurs héritées (ex: des enfants ou relations) continueront de s’appliquer.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Cliquez pour assigner ou modifier la couleur de ce statut.
Elle peut être utilisée pour mettre en évidence les lots de travaux dans le tableau.
index:
no_results_title_text: Aucun statut de lots de travaux pour le moment.
no_results_content_text: Ajouter un nouveau statut
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Clair"
light_high_contrast: "Clair avec contraste élevé"
@@ -623,6 +637,7 @@ fr:
status:
is_closed: "Lot de travaux clôturé"
is_readonly: "Paquet de travail en lecture seule"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Notes"
member:
@@ -959,6 +974,14 @@ fr:
base:
working_days_are_missing: "Au moins un jour de la semaine doit être défini comme jour de travail."
previous_working_day_changes_unprocessed: "Les modifications précédentes de la configuration des jours ouvrables n'ont pas encore été appliquées."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1143,18 +1166,6 @@ fr:
other: "%{count} heures"
updated: "modifié de %{old_value} à %{value}"
logged_for: "Connecté(e) pendant"
- meeting_agenda_item:
- duration:
- added: "défini sur %{value}"
- added_html: "défini sur %{value}"
- removed: "supprimé"
- updated: "modifié de %{old_value} à %{value}"
- updated_html: "modifié de %{old_value} à %{value}"
- position:
- updated: "réorganisé"
- work_package:
- updated: "modifié de %{old_value} à %{value}"
- updated_html: "modifié de %{old_value} à %{value}"
filter:
changeset: "Révisions"
message: "Forums"
@@ -1605,6 +1616,12 @@ fr:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image non exportée."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: j
@@ -1658,7 +1675,7 @@ fr:
dates_changed: "Dates modifiées"
default_attribute_written: "Attributs en lecture seule écrits"
progress_mode_changed_to_status_based: "Mise à jour du calcul de la progression"
- status_p_complete_changed: "Statut du % réalisé modifié"
+ status_changed: "Status '%{status_name}'"
system_update: "Mise à jour du système OpenProject :"
cause_descriptions:
work_package_predecessor_changed_times: par changement vers le prédécesseur %{link}
@@ -1675,8 +1692,9 @@ fr:
working: "%{date} est maintenant un jour ouvrable"
non_working: "%{date} est maintenant un jour non ouvrable"
progress_mode_changed_to_status_based: Le calcul de la progression est désormais basé sur le statut
- status_p_complete_changed: >-
- La valeur du % réalisation du statut « %{status_name} » est passée de %{old_value} à %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
À partir de maintenant, l'activité liée aux liens de fichiers (fichiers stockés sur des supports externes) apparaîtra ici dans l'onglet Activité. Les activités suivantes concernent des liens déjà existants :
@@ -2333,7 +2351,7 @@ fr:
label_workflow: "Flux de travail"
label_workflow_plural: "Flux de travail"
label_workflow_summary: "Résumé"
- label_working_days: "Journées de travail"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 fermée"
other: "%{count} fermées"
@@ -2933,6 +2951,9 @@ fr:
setting_cross_project_work_package_relations: "Autoriser les relations entre lots de travaux de projets différents"
setting_first_week_of_year: "La première semaine de l'année contient"
setting_date_format: "Date"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Langage par défaut"
setting_default_projects_modules: "Modules activés par défaut pour les nouveaux projets"
setting_default_projects_public: "Les nouveaux projets sont publics par défaut"
@@ -2948,6 +2969,12 @@ fr:
setting_feeds_limit: "Limite du contenu du flux"
setting_file_max_size_displayed: "Taille maximale de l'affichage du fichers texte inline"
setting_host_name: "Nom d'hôte"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "L'émail d’activation expire après"
setting_work_package_done_ratio: "Calcul de la progression"
setting_work_package_done_ratio_field: "Basé sur le travail"
@@ -3388,12 +3415,12 @@ fr:
additional_privileges_project_or_group: "Peut avoir des privilèges supplémentaires (en tant que membre du projet ou d'un groupe)"
working_days:
info: >
- Les jours qui ne sont pas sélectionnés sont ignorés lors de la planification des lots de travaux (et non inclus dans le nombre de jours). Ils peuvent être remplacés au niveau du lot de travaux.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Les dates ajoutées à la liste ci-dessous sont considérées comme non fonctionnelles et ignorées lors de la planification des lots de travaux.
change_button: "Changer les jours ouvrables"
warning: >
- La modification des jours de la semaine qui sont considérés comme des jours travaillés ou des jours non travaillés peut affecter les jours de début et de fin de tous les lots de travaux de tous les projets dans ce cas. Veuillez noter que les modifications ne sont appliquées qu'après que vous ayez cliqué sur le bouton appliquer les modifications.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Jours ouvrables** modifiés (%{changes})._
days:
diff --git a/config/locales/crowdin/he.yml b/config/locales/crowdin/he.yml
index e3ed5a70ae05..d9c7f8d99e56 100644
--- a/config/locales/crowdin/he.yml
+++ b/config/locales/crowdin/he.yml
@@ -300,6 +300,12 @@ he:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: There are currently no types available.
form:
@@ -460,12 +466,20 @@ he:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: There are currently no work package statuses.
no_results_content_text: להוסיף סטטוס חדש
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -637,6 +651,7 @@ he:
status:
is_closed: "חבילת עבודה סגורה"
is_readonly: "Work package read-only"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "הערות"
member:
@@ -973,6 +988,14 @@ he:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1173,18 +1196,6 @@ he:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "שינויים"
message: "פורומים"
@@ -1671,6 +1682,12 @@ he:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1724,7 +1741,7 @@ he:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1741,8 +1758,9 @@ he:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2399,7 +2417,7 @@ he:
label_workflow: "זרימת עבודה"
label_workflow_plural: "Workflows"
label_workflow_summary: "פירוט"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "אחד סגור"
other: "%{count} סגורים"
@@ -3003,6 +3021,9 @@ he:
setting_cross_project_work_package_relations: "Allow cross-project work package relations"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "תאריך"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Default language"
setting_default_projects_modules: "Default enabled modules for new projects"
setting_default_projects_public: "New projects are public by default"
@@ -3018,6 +3039,12 @@ he:
setting_feeds_limit: "Feed content limit"
setting_file_max_size_displayed: "Max size of text files displayed inline"
setting_host_name: "Host name"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3461,12 +3488,12 @@ he:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/hi.yml b/config/locales/crowdin/hi.yml
index 739f5f7bfe8e..9aff67140875 100644
--- a/config/locales/crowdin/hi.yml
+++ b/config/locales/crowdin/hi.yml
@@ -300,6 +300,12 @@ hi:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: There are currently no types available.
form:
@@ -447,11 +453,19 @@ hi:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
इस प्राथमिकता का रंग असाइन करने या बदलने के लिए क्लिक करें । यह तालिका में कार्य पैकेज हाइलाइटिंग के लिए उपयोग किया जा सकता है ।
index:
no_results_title_text: There are currently no work package statuses.
no_results_content_text: Add a new status
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -621,6 +635,7 @@ hi:
status:
is_closed: "कार्य पैकेज बंद"
is_readonly: "Work package read-only"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "टिप्पणियाँ"
member:
@@ -957,6 +972,14 @@ hi:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1141,18 +1164,6 @@ hi:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Changesets"
message: "मंच"
@@ -1603,6 +1614,12 @@ hi:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1656,7 +1673,7 @@ hi:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1673,8 +1690,9 @@ hi:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2331,7 +2349,7 @@ hi:
label_workflow: "कार्यप्रवाह"
label_workflow_plural: "Workflows"
label_workflow_summary: "सारांश"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 closed"
other: "%{count} closed"
@@ -2931,6 +2949,9 @@ hi:
setting_cross_project_work_package_relations: "Allow cross-project work package relations"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "तिथि"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Default language"
setting_default_projects_modules: "Default enabled modules for new projects"
setting_default_projects_public: "New projects are public by default"
@@ -2946,6 +2967,12 @@ hi:
setting_feeds_limit: "Feed content limit"
setting_file_max_size_displayed: "Max size of text files displayed inline"
setting_host_name: "Host name"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3387,12 +3414,12 @@ hi:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/hr.yml b/config/locales/crowdin/hr.yml
index 094d9f2a0f94..02f4cef1fd22 100644
--- a/config/locales/crowdin/hr.yml
+++ b/config/locales/crowdin/hr.yml
@@ -300,6 +300,12 @@ hr:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Trenutno nema dostupnih tipova.
form:
@@ -454,12 +460,20 @@ hr:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: Trenutačno ne postoje izvješća o statusu radnih paketa.
no_results_content_text: Novi status
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -630,6 +644,7 @@ hr:
status:
is_closed: "Radni paket zatvoren"
is_readonly: "Work package read-only"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Bilješke"
member:
@@ -966,6 +981,14 @@ hr:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1158,18 +1181,6 @@ hr:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Changesets"
message: "Forumi"
@@ -1638,6 +1649,12 @@ hr:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1691,7 +1708,7 @@ hr:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1708,8 +1725,9 @@ hr:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2366,7 +2384,7 @@ hr:
label_workflow: "Tijek rada"
label_workflow_plural: "Tijek rada"
label_workflow_summary: "Sažetak"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 zaključen"
other: "%{count} zatvorenih"
@@ -2968,6 +2986,9 @@ hr:
setting_cross_project_work_package_relations: "Omogući relacije između unakrsnih projekata"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "Datum"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Zadani jezik"
setting_default_projects_modules: "Zadani omogućeni moduli za nove projekte"
setting_default_projects_public: "Novi projekti su zadani kao javni"
@@ -2983,6 +3004,12 @@ hr:
setting_feeds_limit: "Feed content limit"
setting_file_max_size_displayed: "Maksimalna veličina tesktualnih datoteka prikazanih u liniji"
setting_host_name: "Hostname"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3425,12 +3452,12 @@ hr:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/hu.yml b/config/locales/crowdin/hu.yml
index 5f312592135d..f3fe3fc6d141 100644
--- a/config/locales/crowdin/hu.yml
+++ b/config/locales/crowdin/hu.yml
@@ -299,6 +299,12 @@ hu:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Jelenleg nincs elérhető típus.
form:
@@ -446,12 +452,20 @@ hu:
Jelölje be ezt az opciót, ha ezt az állapotot tartalmazó munkacsomagokat csak olvashatóvá kívánja jelölni. Az állapot kivételével semmilyen attribútum nem módosítható.
Megjegyzés: az örökölt értékek (például a gyermekobjektum vagy a kapcsolatok) továbbra is érvényesek.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Ide kattintva rendelhet vagy változtathatja meg a színét az állapotnak.
Az állapot gomb látható és kiemelhető a feladatcsoport táblázatban.
index:
no_results_title_text: Jelenleg nincsenek feladatcsoport státuszok.
no_results_content_text: Új státusz hozzáadása
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Világos"
light_high_contrast: "Világos, nagy kontraszt"
@@ -620,6 +634,7 @@ hu:
status:
is_closed: "Lezárt feladatcsoport"
is_readonly: "Munkacsomag csak olvasható"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Jegyzet"
member:
@@ -956,6 +971,14 @@ hu:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1140,18 +1163,6 @@ hu:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Commit-ok"
message: "Fórumok"
@@ -1602,6 +1613,12 @@ hu:
pdf_gantt: "PDF Gantt"
image:
omitted: "Kép nem került exportálásra."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: óra
days: nap
@@ -1655,7 +1672,7 @@ hu:
dates_changed: "Dátum módosítva"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject rendszerfrissítés:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1672,8 +1689,9 @@ hu:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2330,7 +2348,7 @@ hu:
label_workflow: "Munkafolyamat"
label_workflow_plural: "A munkafolyamatok"
label_workflow_summary: "Összegzés"
- label_working_days: "Munkanapok"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 lezárt"
other: "%{count} lezárt"
@@ -2929,6 +2947,9 @@ hu:
setting_cross_project_work_package_relations: "Projektek közötti feladatcsoportok kapcsolatainak engedélyezése"
setting_first_week_of_year: "Az év első hete tartalmazza\n"
setting_date_format: "dátum"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Alapértelmezett nyelv"
setting_default_projects_modules: "Az új projektekben alapértelmezetten engedélyezett modulok"
setting_default_projects_public: "Új projektek nyilvánosak alapértelmezetten"
@@ -2944,6 +2965,12 @@ hu:
setting_feeds_limit: "Tartalom szintjének a korlátja"
setting_file_max_size_displayed: "A szöveg fájl sorainak maximum mérete megjelenítéskor"
setting_host_name: "Gazdagép neve"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Az aktivációs email lejár ekkor"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3385,12 +3412,12 @@ hu:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/id.yml b/config/locales/crowdin/id.yml
index 483b351665fa..498130de3d37 100644
--- a/config/locales/crowdin/id.yml
+++ b/config/locales/crowdin/id.yml
@@ -294,6 +294,12 @@ id:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: There are currently no types available.
form:
@@ -436,12 +442,20 @@ id:
Tidak ada atribut yang dapat diubah kecuali status.
Catatan: Nilai yang diwariskan (mis., dari anak atau relasi) akan tetap berlaku.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Klik untuk ditugaskan atau mengubah warna status ini.
Itu ditampilkan di tombol status dan dapat digunakan untuk menyorot paket kerja di tabel.
index:
no_results_title_text: There are currently no work package statuses.
no_results_content_text: Add a new status
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -609,6 +623,7 @@ id:
status:
is_closed: "Paket-Penugasan telah berakhir"
is_readonly: "Hanya baca paket kerja"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Note"
member:
@@ -945,6 +960,14 @@ id:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1121,18 +1144,6 @@ id:
other: "Satu\n %{count} jam\n\n Lainnya\n %{count} jam"
updated: "diubah dari %{old_value} menjadi %{value}"
logged_for: "Masuk untuk"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "diubah dari %{old_value} menjadi %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "diubah dari %{old_value} menjadi %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Set perubahan"
message: "Forum"
@@ -1565,6 +1576,12 @@ id:
pdf_gantt: "PDF Gantt"
image:
omitted: "Gambar tidak diekspor."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: j
days: h
@@ -1618,7 +1635,7 @@ id:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1635,8 +1652,9 @@ id:
working: "%{date} sekarang berkerja"
non_working: "%{date} sekarang tidak berkerja"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2293,7 +2311,7 @@ id:
label_workflow: "Workflow"
label_workflow_plural: "Alur kerja"
label_workflow_summary: "Ringkasan"
- label_working_days: "Hari kerja"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 closed"
other: "%{count} tertutup"
@@ -2887,6 +2905,9 @@ id:
setting_cross_project_work_package_relations: "Mungkinkan relasi cross-project Paket-Penugasan"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "Tanggal"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Bahasa default"
setting_default_projects_modules: "Modul default aktif untuk Project baru"
setting_default_projects_public: "Project baru default untuk publik"
@@ -2902,6 +2923,12 @@ id:
setting_feeds_limit: "Batasan konten feed"
setting_file_max_size_displayed: "Ukuran maks. file teks yang ditampilkan inline"
setting_host_name: "Nama host"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3342,12 +3369,12 @@ id:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Hari yang tidak dipilih akan dilewati saat menjadwalkan paket pekerjaan (dan tidak termasuk dalam hitungan hari). Ini dapat diganti pada tingkat paket kerja.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Tanggal yang ditambahkan ke daftar di bawah ini dianggap tidak berfungsi dan dilewati saat menjadwalkan paket pekerjaan.
change_button: "Ubah hari kerja"
warning: >
- Mengubah hari mana dalam seminggu yang dianggap sebagai hari kerja atau bukan hari kerja dapat memengaruhi hari mulai dan selesai dari semua paket pekerjaan di semua proyek dalam contoh ini. Harap perhatikan bahwa perubahan hanya diterapkan setelah Anda mengeklik tombol terapkan perubahan.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Hari kerja** berubah (%{changes})._
days:
diff --git a/config/locales/crowdin/it.yml b/config/locales/crowdin/it.yml
index 5e01902655ac..458b23cdf021 100644
--- a/config/locales/crowdin/it.yml
+++ b/config/locales/crowdin/it.yml
@@ -297,6 +297,12 @@ it:
is_required_blank_slate:
heading: Richiesto in tutti i progetti
description: Questo attributo di progetto è attivato in tutti i progetti, poiché l'opzione "Richiesto in tutti i progetti" è selezionata. Non può essere disattivato per i singoli progetti.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Al momento non sono disponibili tipi.
form:
@@ -445,12 +451,20 @@ it:
Nessun attributo può essere modificato ad eccezione dello stato.
Nota : i valori ereditati (ad esempio, dai figli o dalle relazioni) verranno comunque applicati.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Clicca per assegnare o modificare il colore di questo stato.
Viene mostrato come tasto di stato e può essere utilizzato per evidenziare le macro-attività nella tabella.
index:
no_results_title_text: Al momento non vi sono relazioni sullo stato delle macro-attività.
no_results_content_text: Aggiungi un nuovo stato
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Chiaro"
light_high_contrast: "Chiaro ad alto contrasto"
@@ -620,6 +634,7 @@ it:
status:
is_closed: "Macro-attività chiusa"
is_readonly: "Pacchetto di lavoro di sola lettura"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Note"
member:
@@ -956,6 +971,14 @@ it:
base:
working_days_are_missing: "Almeno un giorno della settimana deve essere impostato giorno lavorativo."
previous_working_day_changes_unprocessed: "Le modifiche precedenti alla configurazione dei giorni lavorativi non sono ancora state applicate."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1140,18 +1163,6 @@ it:
other: "%{count} ore"
updated: "modificato da %{old_value} a %{value}"
logged_for: "Registrato per"
- meeting_agenda_item:
- duration:
- added: "impostato a %{value}"
- added_html: "impostato a %{value}"
- removed: "rimosso"
- updated: "modificato da %{old_value} a %{value}"
- updated_html: "modificato da %{old_value} a %{value}"
- position:
- updated: "riordinato"
- work_package:
- updated: "modificato da %{old_value} a %{value}"
- updated_html: "modificato da %{old_value} a %{value}"
filter:
changeset: "Insiemi di modifiche"
message: "Forum"
@@ -1602,6 +1613,12 @@ it:
pdf_gantt: "Gantt in PDF"
image:
omitted: "Immagine non esportata."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: o
days: g
@@ -1655,7 +1672,7 @@ it:
dates_changed: "Date cambiate"
default_attribute_written: "Attributi di sola lettura scritti"
progress_mode_changed_to_status_based: "Calcolo dei progressi aggiornato"
- status_p_complete_changed: "Stato di % completamento modificato"
+ status_changed: "Status '%{status_name}'"
system_update: "Aggiornamento del sistema OpenProject:"
cause_descriptions:
work_package_predecessor_changed_times: da modifiche al predecessore %{link}
@@ -1672,8 +1689,9 @@ it:
working: "%{date} è ora lavorativo"
non_working: "%{date} è ora non lavorativo"
progress_mode_changed_to_status_based: La modalità di calcolo dell'avanzamento è impostata in funzione dello stato.
- status_p_complete_changed: >-
- Il valore di % completamento per lo stato "%{status_name}" è cambiato da %{old_value}% a %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
D'ora in poi, l'attività relativa ai collegamenti ai file (file archiviati in archivi esterni) verrà visualizzata qui nella scheda Attività. Di seguito trovi attività riguardanti link già esistenti:
@@ -2330,7 +2348,7 @@ it:
label_workflow: "Flusso di lavoro"
label_workflow_plural: "Flussi di lavoro"
label_workflow_summary: "Sommario"
- label_working_days: "Giorni lavorativi"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 chiuso"
other: "%{count} chiusi"
@@ -2930,6 +2948,9 @@ it:
setting_cross_project_work_package_relations: "Consenti di correlare macro-attività tra più progetti"
setting_first_week_of_year: "La prima settimana dell'anno contiene"
setting_date_format: "Data"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Linguaggio predefinito"
setting_default_projects_modules: "Moduli abilitati in automatico su nuovi progetti"
setting_default_projects_public: "I nuovi progetti sono pubblici come impostazione predefinita"
@@ -2945,6 +2966,12 @@ it:
setting_feeds_limit: "Limite al contenuto del contributo"
setting_file_max_size_displayed: "Dimensione massima dei file di testo visualizzati inline"
setting_host_name: "Nome dell'Host"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "L'email di attivazione scade dopo"
setting_work_package_done_ratio: "Calcolo dei progressi"
setting_work_package_done_ratio_field: "Basato sul lavoro"
@@ -3386,12 +3413,12 @@ it:
additional_privileges_project_or_group: "Potrebbe avere privilegi aggiuntivi (in quanto membro del progetto o del gruppo)"
working_days:
info: >
- I giorni non selezionati vengono saltati durante la pianificazione delle macro-attività (e non inclusi nel conteggio dei giorni). Questi possono essere sovrascritti a livello di macro-attività.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Le date aggiunte all'elenco seguente sono considerate non lavorative e saltate durante la pianificazione delle macro-attività.
change_button: "Cambia giorni lavorativi"
warning: >
- La modifica dei giorni della settimana da considerare lavorativi o non lavorativi può influire sui giorni di inizio e di fine di tutte le macro-attività in tutti i progetti in questa istanza. Tieni presente che le modifiche vengono applicate solo dopo aver fatto clic sul pulsante Applica modifiche.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Giorni lavorativi** cambiati (%{changes})._
days:
diff --git a/config/locales/crowdin/ja.yml b/config/locales/crowdin/ja.yml
index d47f5f37f7ff..7da60486d7b5 100644
--- a/config/locales/crowdin/ja.yml
+++ b/config/locales/crowdin/ja.yml
@@ -298,6 +298,12 @@ ja:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: 現在、有効な種類はありません。
form:
@@ -438,12 +444,20 @@ ja:
status_readonly_html: |
このステータスのワークパッケージを読み取り専用としてマークするにはこのオプションを選択します。ステータスを除く属性は変更できません。 注:継承された値(子や関係)は引き続き適用されます。
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
このステータスの色を割り当てたり変更する場合にクリックします。
ステータスボタンに表示され、テーブル内のワークパッケージを強調表示するために使用できます。
index:
no_results_title_text: 現在、ワークパッケージのステータスはありません。
no_results_content_text: 新しいステータスを追加
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -612,6 +626,7 @@ ja:
status:
is_closed: "作業が完了"
is_readonly: "読み取り専用のワークパッケージ"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "注記"
member:
@@ -948,6 +963,14 @@ ja:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1124,18 +1147,6 @@ ja:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "更新履歴"
message: "フォーラム"
@@ -1568,6 +1579,12 @@ ja:
pdf_gantt: "PDF Gantt"
image:
omitted: "画像はエクスポートされませんでした。"
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1621,7 +1638,7 @@ ja:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1638,8 +1655,9 @@ ja:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2296,7 +2314,7 @@ ja:
label_workflow: "ワークフロー"
label_workflow_plural: "ワークフロー"
label_workflow_summary: "サマリ"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1件完了"
other: "%{count}件完了"
@@ -2894,6 +2912,9 @@ ja:
setting_cross_project_work_package_relations: "他プロジェクトとの間にワークパッケージの関連付けを許可する"
setting_first_week_of_year: "年の最初の週に含む"
setting_date_format: "日付"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "デフォルトの言語"
setting_default_projects_modules: "新規プロジェクトにおいてデフォルトで有効になるモジュール"
setting_default_projects_public: "デフォルトで新しいプロジェクトは公開にする"
@@ -2909,6 +2930,12 @@ ja:
setting_feeds_limit: "フィードの項目数の上限"
setting_file_max_size_displayed: "画面表示するテキストファイルの最大サイズ"
setting_host_name: "ホスト名"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "アクティベーションのメールは次で有効期限切れ"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3348,12 +3375,12 @@ ja:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "営業日を変更する"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/js-af.yml b/config/locales/crowdin/js-af.yml
index c796bd43d7d0..06d0484df2aa 100644
--- a/config/locales/crowdin/js-af.yml
+++ b/config/locales/crowdin/js-af.yml
@@ -274,6 +274,11 @@ af:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "on"
@@ -1282,6 +1287,11 @@ af:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Continue"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1342,7 +1352,7 @@ af:
remove: "Remove"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Close"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-ar.yml b/config/locales/crowdin/js-ar.yml
index eec6a803965e..fa96ca430ccf 100644
--- a/config/locales/crowdin/js-ar.yml
+++ b/config/locales/crowdin/js-ar.yml
@@ -274,6 +274,11 @@ ar:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "في"
@@ -1294,6 +1299,11 @@ ar:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Continue"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1354,7 +1364,7 @@ ar:
remove: "إزالة"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "أغلِق"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-az.yml b/config/locales/crowdin/js-az.yml
index 9f843e0cdd3b..cad353152936 100644
--- a/config/locales/crowdin/js-az.yml
+++ b/config/locales/crowdin/js-az.yml
@@ -274,6 +274,11 @@ az:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "on"
@@ -1282,6 +1287,11 @@ az:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Davam"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1342,7 +1352,7 @@ az:
remove: "Remove"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Bağla"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-be.yml b/config/locales/crowdin/js-be.yml
index d05d20dba777..740a1bfff54e 100644
--- a/config/locales/crowdin/js-be.yml
+++ b/config/locales/crowdin/js-be.yml
@@ -274,6 +274,11 @@ be:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "on"
@@ -1288,6 +1293,11 @@ be:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Continue"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1348,7 +1358,7 @@ be:
remove: "Remove"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Зачыніць"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-bg.yml b/config/locales/crowdin/js-bg.yml
index 1308efbe79a2..cbd513bf16bd 100644
--- a/config/locales/crowdin/js-bg.yml
+++ b/config/locales/crowdin/js-bg.yml
@@ -274,6 +274,11 @@ bg:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "на"
@@ -1282,6 +1287,11 @@ bg:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Продължаване"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1342,7 +1352,7 @@ bg:
remove: "Премахване"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Close"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-ca.yml b/config/locales/crowdin/js-ca.yml
index 34fda75c23c8..08fe1aa5995b 100644
--- a/config/locales/crowdin/js-ca.yml
+++ b/config/locales/crowdin/js-ca.yml
@@ -274,6 +274,11 @@ ca:
warning: >
Els canvis poden tardar un temps a ser aplicats. Et notificarem un cop s'hagin actualitzat tots els paquets de treball rellevants.
Estàs segur que vols continuar?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "en"
@@ -1282,6 +1287,11 @@ ca:
placeholder: "L'usuari de marcador de posició ara pot ser utilitzat a %{project}. Per tant, ja pots planejar amb aquest usuari i assignar-li paquets de treball."
group: "El grup és ara part de %{project}. Per tant, ja pots planejar amb aquest grup i assignar-li paquets de treball."
next_button: "Continua"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1342,7 +1352,7 @@ ca:
remove: "Eliminar"
drop_modal:
focus_grab: "Estàs en un focus ancorat per a finestres emergents. Fes clic a shift+tab per tornar a l'element que ha activat la finestra emergent."
- Close: "Tanca"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-ckb-IR.yml b/config/locales/crowdin/js-ckb-IR.yml
index 90413df16cf7..8fe2f55b203c 100644
--- a/config/locales/crowdin/js-ckb-IR.yml
+++ b/config/locales/crowdin/js-ckb-IR.yml
@@ -274,6 +274,11 @@ ckb-IR:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "on"
@@ -1282,6 +1287,11 @@ ckb-IR:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Continue"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1342,7 +1352,7 @@ ckb-IR:
remove: "Remove"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Close"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-cs.yml b/config/locales/crowdin/js-cs.yml
index 19e5671b0fb5..b67c8300404b 100644
--- a/config/locales/crowdin/js-cs.yml
+++ b/config/locales/crowdin/js-cs.yml
@@ -273,6 +273,11 @@ cs:
change_description: "Změna, těch dnů v týdnu, které jsou považovány za pracovní dny, může ovlivnit datum zahájení a datum ukončení všech pracovních balíčků ve všech projektech \n v této instanci."
warning: >
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "zapnuto"
@@ -1287,6 +1292,11 @@ cs:
placeholder: "Zástupného uživatele lze nyní použít v %{project}. Mezitím již můžete plánovat s tímto uživatelem a přiřadit mu například pracovní balíčky."
group: "Skupina je nyní součástí %{project}. Mezitím již můžete s touto skupinou plánovat a přiřadit například pracovní balíčky."
next_button: "Pokračovat"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1347,7 +1357,7 @@ cs:
remove: "Odstranit"
drop_modal:
focus_grab: "Toto je ukotvení pro modaly. Stisknutím karty shift+b se vrátíte k aktivačnímu prvku modalu."
- Close: "Zavřít"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Vypršel časový limit"
diff --git a/config/locales/crowdin/js-da.yml b/config/locales/crowdin/js-da.yml
index 10fbeacf9b99..b8c97debaff0 100644
--- a/config/locales/crowdin/js-da.yml
+++ b/config/locales/crowdin/js-da.yml
@@ -273,6 +273,11 @@ da:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "på"
@@ -1281,6 +1286,11 @@ da:
placeholder: "Pladsholderen kan nu bruges i %{project}. I mellemtiden kan du allerede planlægge med den pågældende bruger og tildele arbejdspakker for eksempel."
group: "Gruppen er nu en del af %{project}. I mellemtiden kan du allerede planlægge med denne gruppe og tildele arbejdspakker for eksempel."
next_button: "Fortsæt"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1341,7 +1351,7 @@ da:
remove: "Fjern"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Luk"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-de.yml b/config/locales/crowdin/js-de.yml
index eb965cbf0d23..06f59d1c38a0 100644
--- a/config/locales/crowdin/js-de.yml
+++ b/config/locales/crowdin/js-de.yml
@@ -273,6 +273,11 @@ de:
warning: >
Es kann einige Zeit dauern, bis die Änderungen wirksam werden. Sie werden benachrichtigt, wenn alle relevanten Arbeitspakete aktualisiert worden sind.
Sind Sie sicher, dass Sie fortfahren möchten?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "am"
@@ -1281,6 +1286,11 @@ de:
placeholder: "Der Platzhalter kann jetzt in %{project} verwendet werden. In der Zwischenzeit können Sie bereits mit diesem Benutzer planen und beispielsweise Arbeitspakete zuweisen."
group: "Die Gruppe ist nun %{project} zugewiesen. In der Zwischenzeit können Sie bereits mit dieser Gruppe planen und ihr zum Beispiel Arbeitspakete zuweisen."
next_button: "Fortfahren"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "Sie haben keine favorisierten Projekte"
no_results_subtext: "Fügen Sie ein oder mehrere Projekte als Favorit in ihrer Übersicht oder in einer Projektliste hinzu."
@@ -1341,7 +1351,7 @@ de:
remove: "Entfernen"
drop_modal:
focus_grab: "Dies ist ein Fokusanker für Modale. Drücken Sie Shift+Tab um zum vorherigen öffnenden Element zurückzukehren."
- Close: "Schließen"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-el.yml b/config/locales/crowdin/js-el.yml
index 39ef043f8ce9..fadaa36f67b4 100644
--- a/config/locales/crowdin/js-el.yml
+++ b/config/locales/crowdin/js-el.yml
@@ -273,6 +273,11 @@ el:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "σε"
@@ -1281,6 +1286,11 @@ el:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "Η ομάδα είναι τώρα μέρος του %{project}. Εν τω μεταξύ, μπορείτε να προγραμματίσετε ήδη με αυτή την ομάδα και να αντιστοιχίσετε πακέτα εργασίας."
next_button: "Συνέχεια"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1341,7 +1351,7 @@ el:
remove: "Αφαίρεση"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Κλείσιμο"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-eo.yml b/config/locales/crowdin/js-eo.yml
index 79d4bc1d92fd..75d8afe65a00 100644
--- a/config/locales/crowdin/js-eo.yml
+++ b/config/locales/crowdin/js-eo.yml
@@ -274,6 +274,11 @@ eo:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "je"
@@ -1282,6 +1287,11 @@ eo:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Daŭrigi"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1342,7 +1352,7 @@ eo:
remove: "Forigi"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Fermi"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-es.yml b/config/locales/crowdin/js-es.yml
index e140870bacf9..631c1f63927c 100644
--- a/config/locales/crowdin/js-es.yml
+++ b/config/locales/crowdin/js-es.yml
@@ -274,6 +274,11 @@ es:
warning: >
Los cambios pueden tardar algún tiempo en surtir efecto. Se le notificará cuando todos los paquetes de trabajo relevantes hayan sido actualizados.
¿Está seguro de que desea continuar?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "en"
@@ -984,7 +989,7 @@ es:
createdAt: "Creado en"
description: "Descripción"
date: "Fecha"
- percentComplete: "% compleado"
+ percentComplete: "% Completado"
percentCompleteAlternative: "Progreso"
dueDate: "Fecha de finalización"
duration: "Duración"
@@ -1282,6 +1287,11 @@ es:
placeholder: "El marcador de posición ya puede usarse en %{project}. Mientras tanto, puede crear planes con ese usuario y asignarle paquetes de trabajo."
group: "El grupo ya forma parte de %{project}. Mientras tanto, puede crear planes con ese grupo y asignar paquetes de trabajo a este."
next_button: "Continuar"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "No tiene proyectos favoritos"
no_results_subtext: "Añada uno o varios proyectos como favoritos a través del resumen del proyecto o en una lista de proyectos."
@@ -1342,7 +1352,7 @@ es:
remove: "Eliminar"
drop_modal:
focus_grab: "Este es una ancla de enfoque para modales. Presione shift+tab para volver al elemento que activa el modal."
- Close: "Cerrar"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-et.yml b/config/locales/crowdin/js-et.yml
index 05d298546def..b37cf89f73c9 100644
--- a/config/locales/crowdin/js-et.yml
+++ b/config/locales/crowdin/js-et.yml
@@ -274,6 +274,11 @@ et:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "on"
@@ -1282,6 +1287,11 @@ et:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Jätka"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1342,7 +1352,7 @@ et:
remove: "Eemalda"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Sulge"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-eu.yml b/config/locales/crowdin/js-eu.yml
index 8c441ef515aa..cb5eb01c8734 100644
--- a/config/locales/crowdin/js-eu.yml
+++ b/config/locales/crowdin/js-eu.yml
@@ -274,6 +274,11 @@ eu:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "on"
@@ -1282,6 +1287,11 @@ eu:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Continue"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1342,7 +1352,7 @@ eu:
remove: "Remove"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Itxi"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-fa.yml b/config/locales/crowdin/js-fa.yml
index e8a45f738d48..efbfd32f297e 100644
--- a/config/locales/crowdin/js-fa.yml
+++ b/config/locales/crowdin/js-fa.yml
@@ -274,6 +274,11 @@ fa:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "برخط"
@@ -1282,6 +1287,11 @@ fa:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Continue"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1342,7 +1352,7 @@ fa:
remove: "Remove"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Close"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-fi.yml b/config/locales/crowdin/js-fi.yml
index 36d03c12a20f..ce230f101dd5 100644
--- a/config/locales/crowdin/js-fi.yml
+++ b/config/locales/crowdin/js-fi.yml
@@ -274,6 +274,11 @@ fi:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "päälle"
@@ -1282,6 +1287,11 @@ fi:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Jatka"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1342,7 +1352,7 @@ fi:
remove: "Poista"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Sulje"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-fil.yml b/config/locales/crowdin/js-fil.yml
index 0f0015c823ad..16e8933fad45 100644
--- a/config/locales/crowdin/js-fil.yml
+++ b/config/locales/crowdin/js-fil.yml
@@ -274,6 +274,11 @@ fil:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "sa"
@@ -1282,6 +1287,11 @@ fil:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Magpatuloy"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1342,7 +1352,7 @@ fil:
remove: "Tanggalin"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Isara"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-fr.yml b/config/locales/crowdin/js-fr.yml
index b4fdbeb411f5..b8333debc36e 100644
--- a/config/locales/crowdin/js-fr.yml
+++ b/config/locales/crowdin/js-fr.yml
@@ -274,6 +274,11 @@ fr:
warning: >
Les modifications pourraient prendre un certain temps pour être appliquées. Vous serez averti(e) lorsque tous les lots de travaux pertinents auront été mis à jour.
Voulez-vous continuer ?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "le"
@@ -1282,6 +1287,11 @@ fr:
placeholder: "Le utilisateur fictif peut maintenant être utilisé dans %{project}. En attendant, vous pouvez déjà planifier des taches avec cet utilisateur et l'assigner à des lots de travaux par exemple."
group: "Le groupe fait maintenant partie du %{project}. Entre-temps, vous pouvez déjà planifier avec ce groupe et l'assigner des lots de travaux par exemple."
next_button: "Continuer"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "Vous n'avez pas de projet favori"
no_results_subtext: "Ajoutez un ou plusieurs projets en tant que favoris via leur vue d'ensemble ou dans une liste de projets."
@@ -1342,7 +1352,7 @@ fr:
remove: "Supprimer"
drop_modal:
focus_grab: "Il s'agit d'une ancre de mise au point pour les fenêtres modales. Appuyez sur Maj+Tab pour revenir à l'élément de déclenchement modal."
- Close: "Fermer"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-he.yml b/config/locales/crowdin/js-he.yml
index f61ec81138e0..8c679ec6fe2d 100644
--- a/config/locales/crowdin/js-he.yml
+++ b/config/locales/crowdin/js-he.yml
@@ -274,6 +274,11 @@ he:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "פועל"
@@ -1288,6 +1293,11 @@ he:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Continue"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1348,7 +1358,7 @@ he:
remove: "Remove"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "סגור"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-hi.yml b/config/locales/crowdin/js-hi.yml
index caa98984784e..726e7ef078a4 100644
--- a/config/locales/crowdin/js-hi.yml
+++ b/config/locales/crowdin/js-hi.yml
@@ -274,6 +274,11 @@ hi:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "पर"
@@ -1282,6 +1287,11 @@ hi:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Continue"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1342,7 +1352,7 @@ hi:
remove: "Remove"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "बंद करें"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-hr.yml b/config/locales/crowdin/js-hr.yml
index 71252fa651fd..c2a6f1cf4db2 100644
--- a/config/locales/crowdin/js-hr.yml
+++ b/config/locales/crowdin/js-hr.yml
@@ -274,6 +274,11 @@ hr:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "na"
@@ -1285,6 +1290,11 @@ hr:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Nastavi"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1345,7 +1355,7 @@ hr:
remove: "Ukloni"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Zatvori"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-hu.yml b/config/locales/crowdin/js-hu.yml
index 0f4f0cec1a51..5250ed74383d 100644
--- a/config/locales/crowdin/js-hu.yml
+++ b/config/locales/crowdin/js-hu.yml
@@ -274,6 +274,11 @@ hu:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "be"
@@ -1282,6 +1287,11 @@ hu:
placeholder: "A tesztfelhasználó mostantól használható a %{project}-ben. Eközben már tervezhetünk ezzel a felhasználóval, és például munkacsomagokat rendelhetünk hozzá."
group: "A csoport mostantól a %{project} része. Eközben már tervezhet ezzel a csoporttal, és például munkacsomagokat rendelhet hozzá.\n"
next_button: "Folytatás"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1342,7 +1352,7 @@ hu:
remove: "Eltávolítás"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Bezár"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-id.yml b/config/locales/crowdin/js-id.yml
index 6aaafca3fcf1..7d81b5a34434 100644
--- a/config/locales/crowdin/js-id.yml
+++ b/config/locales/crowdin/js-id.yml
@@ -274,6 +274,11 @@ id:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "pada"
@@ -1279,6 +1284,11 @@ id:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Lanjut"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1339,7 +1349,7 @@ id:
remove: "Remove"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Tutup"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-it.yml b/config/locales/crowdin/js-it.yml
index 65b4a7dd5e60..0ba584eaf4a8 100644
--- a/config/locales/crowdin/js-it.yml
+++ b/config/locales/crowdin/js-it.yml
@@ -274,6 +274,11 @@ it:
warning: >
L'applicazione delle modifiche potrebbe richiedere del tempo. Riceverai una notifica quando tutti i pacchetti di lavoro pertinenti saranno aggiornati.
Vuoi davvero continuare?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "il"
@@ -1282,6 +1287,11 @@ it:
placeholder: "Il segnaposto è ora utilizzabile in %{project}. Nel mentre puoi ad esempio già pianificare con quell'utente e assegnare pacchetti di lavoro."
group: "Il gruppo è ora parte di %{project}. Nel mentre puoi ad esempio già pianificare con quel gruppo e assegnare pacchetti di lavoro."
next_button: "Continua"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "Non hai progetti preferiti"
no_results_subtext: "Aggiungi uno o più progetti come preferiti dalla rispettiva panoramica o da una lista di progetti."
@@ -1342,7 +1352,7 @@ it:
remove: "Rimuovi"
drop_modal:
focus_grab: "Questo è un punto focale per i modali. Premere MAIUSC+TAB per tornare all'elemento scatenante modale."
- Close: "Chiuso"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-ja.yml b/config/locales/crowdin/js-ja.yml
index 409c1f7409b1..83ab1924dfd3 100644
--- a/config/locales/crowdin/js-ja.yml
+++ b/config/locales/crowdin/js-ja.yml
@@ -275,6 +275,11 @@ ja:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "オン"
@@ -1280,6 +1285,11 @@ ja:
placeholder: "プレースホルダーを %{project} で使用できるようになりました。一方で、そのユーザを使って計画を立てたり、ワークパッケージを割り当てたりすることができます。"
group: "グループは %{project} の一部になりました。一方で、そのグループを使って計画を立てたり、ワークパッケージを割り当てたりすることができます。"
next_button: "続行"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1340,7 +1350,7 @@ ja:
remove: "削除"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "閉じる"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-ka.yml b/config/locales/crowdin/js-ka.yml
index 466b6e93a133..cdeeb4533666 100644
--- a/config/locales/crowdin/js-ka.yml
+++ b/config/locales/crowdin/js-ka.yml
@@ -274,6 +274,11 @@ ka:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "დრო"
@@ -1282,6 +1287,11 @@ ka:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "გაგრძელება"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1342,7 +1352,7 @@ ka:
remove: "წაშლა"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "დახურვა"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-kk.yml b/config/locales/crowdin/js-kk.yml
index 6658c5565428..4f5ea4b84d79 100644
--- a/config/locales/crowdin/js-kk.yml
+++ b/config/locales/crowdin/js-kk.yml
@@ -274,6 +274,11 @@ kk:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "on"
@@ -1282,6 +1287,11 @@ kk:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Continue"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1342,7 +1352,7 @@ kk:
remove: "Remove"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Close"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-ko.yml b/config/locales/crowdin/js-ko.yml
index 23d2a0718237..9a2f670ed8c4 100644
--- a/config/locales/crowdin/js-ko.yml
+++ b/config/locales/crowdin/js-ko.yml
@@ -274,6 +274,11 @@ ko:
warning: >
변경 사항이 적용되는 데 시간이 걸릴 수 있습니다. 모든 관련 작업 패키지가 업데이트되면 알림이 전송됩니다.
계속하시겠습니까?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "에"
@@ -1279,6 +1284,11 @@ ko:
placeholder: "이제 %{project}에서 이 플레이스홀더를 사용할 수 있게 되었습니다. 한편 당신은 해당 사용자에 대한 계획을 세우거나 작업 패키지를 할당할 수 있습니다."
group: "이제 이 그룹은 %{project}의 일부입니다. 한편 당신은 해당 사용자에 대한 계획을 세우거나 작업 패키지를 할당할 수 있습니다."
next_button: "계속"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "즐겨 찾는 프로젝트가 없습니다"
no_results_subtext: "개요 또는 프로젝트 목록에서 하나 이상의 프로젝트를 즐겨찾기로 추가하세요."
@@ -1339,7 +1349,7 @@ ko:
remove: "제거"
drop_modal:
focus_grab: "모달용 포커스 앵커입니다. 모달 트리거 요소로 돌아가려면 shift+tab을 누르세요."
- Close: "닫기"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-lt.yml b/config/locales/crowdin/js-lt.yml
index 2623c581e189..209637feef8e 100644
--- a/config/locales/crowdin/js-lt.yml
+++ b/config/locales/crowdin/js-lt.yml
@@ -274,6 +274,11 @@ lt:
warning: >
Pakeitimų įsigaliojimas gali užtrukti. Jums bus pranešta, kai visi susiję darbo paketai bus atnaujinti.
Ar tikrai norite tęsti?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "įjungta"
@@ -1288,6 +1293,11 @@ lt:
placeholder: "Statytinis naudotojas gali prisijungti ir pasiekti %{project}. Tuo pačiu, jūs jau galite planuoti darbus su šiuo naudotoju ir pavyzdžiui priskirti jam darbo užduotis."
group: "Grupė jau tapo %{project} dalimi. Tuo pačiu, jūs jau galite planuoti darbus su šia grupe ir pavyzdžiui priskirti jai darbo užduotis."
next_button: "Tęsti"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "Jūs neturite mėgstamų projektų"
no_results_subtext: "Pridėkite vieną ar kelis projektus kaip mėgiamus jų apžvalgoje ar projektų sąraše."
@@ -1348,7 +1358,7 @@ lt:
remove: "Pašalinti"
drop_modal:
focus_grab: "Tai fokuso inkaras modalams. Spauskite shift+tab, kad grįžtumėte į modalinių trigerių elementą."
- Close: "Uždaryti"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-lv.yml b/config/locales/crowdin/js-lv.yml
index 4649cd314eb3..e69ab5f81739 100644
--- a/config/locales/crowdin/js-lv.yml
+++ b/config/locales/crowdin/js-lv.yml
@@ -274,6 +274,11 @@ lv:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: " "
@@ -1285,6 +1290,11 @@ lv:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Continue"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1345,7 +1355,7 @@ lv:
remove: "Noņemt"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Aizvērt"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-mn.yml b/config/locales/crowdin/js-mn.yml
index 4ca68f6f6834..23c9f97d706b 100644
--- a/config/locales/crowdin/js-mn.yml
+++ b/config/locales/crowdin/js-mn.yml
@@ -274,6 +274,11 @@ mn:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "on"
@@ -1282,6 +1287,11 @@ mn:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Continue"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1342,7 +1352,7 @@ mn:
remove: "Remove"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Close"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-ms.yml b/config/locales/crowdin/js-ms.yml
index 0f5be795c643..7563f36c8cdc 100644
--- a/config/locales/crowdin/js-ms.yml
+++ b/config/locales/crowdin/js-ms.yml
@@ -22,7 +22,7 @@
ms:
js:
ajax:
- hide: "Sorokkan"
+ hide: "Sembunyikan"
loading: "Memuatkan..."
updating: "Mengemas kini..."
attachments:
@@ -146,7 +146,7 @@ ms:
manual: "Tukar ke sumber Markdown"
wysiwyg: "Tukar ke editor WYSIWYG"
macro:
- error: "Tidak dapat kembangkan macro: %{message}"
+ error: "Tidak dapat kembangkan makro: %{message}"
attribute_reference:
macro_help_tooltip: "Bahagian teks ini sedang dihasilkan secara dinamik oleh makro."
not_found: "Sumber yang diminta tidak dapat ditemui"
@@ -168,7 +168,7 @@ ms:
macros: "Makro-makro"
chose_macro: "Pilih makro"
toc: "Jadual kandungan"
- toolbar_help: "Klik untuk memilih widget dan tunjuk toolbar. Klik dua kali untuk edit widget"
+ toolbar_help: "Klik untuk memilih widget dan paparkan toolbar. Klik dua kali untuk edit widget"
wiki_page_include:
button: "Sertakan kandungan halaman wiki lain"
text: "[Placeholder] Termasuk halaman wiki"
@@ -205,7 +205,7 @@ ms:
trial:
confirmation: "Pengesahan alamat e-mel "
confirmation_info: >
- Kami telah menghantar satu e-mel kepada anda pada %{date} kepada %{email}. Sila semak peti masuk anda dan klik pautan pengesahan yang disediakan untuk memulakan percubaan 14 hari anda.
+ Kami telah menghantar e-mel kepada anda pada %{date} di %{email}. Sila semak peti masuk anda dan klik pautan pengesahan yang disediakan untuk memulakan percubaan 14 hari anda.
form:
general_consent: >
Saya bersetuju dengan syarat-syarat perkhidmatan dan polisi privasi.
@@ -247,7 +247,7 @@ ms:
premium_features: "Tambahan Enterprise"
premium_features_text: "Board Agile, tema tersuai dan logo, graf, aliran kerja yang cerdas dengan tindakan tersuai, carian teks penuh untuk lampiran pakej kerja dan pelbagai pilihan ruang tersuai."
professional_support: "Sokongan profesional"
- professional_support_text: "Dapatkan sokongan yang boleh dipercayai, sentuhan tinggi daripada jurutera sokongan kanan dengan pengetahuan pakar tentang menjalankan OpenProject dalam persekitaran perniagaan yang kritikal."
+ professional_support_text: "Dapatkan sokongan yang boleh dipercayai, sokongan peribadi yang berkualiti tinggi daripada jurutera sokongan berpengalaman dengan pengetahuan pakar tentang menjalankan OpenProject dalam persekitaran perniagaan yang kritikal."
button_start_trial: "Mulakan percubaan percuma"
button_upgrade: "Naik taraf sekarang"
button_contact_us: "Hubungi kami untuk demo"
@@ -267,13 +267,18 @@ ms:
new_date: "(baharu)"
add_non_working_day: "Hari tidak bekerja"
already_added_error: "Hari tidak bekerja untuk tarikh ini sudah ada. Hanya boleh mempunyai satu hari tidak bekerja dicipta untuk setiap tarikh yang unik."
- change_button: "Simpan dan jadual semula"
+ change_button: "Simpan dan jadualkan semula"
change_title: "Tukar hari bekerja"
removed_title: "Anda akan mengeluarkan hari berikut dari senarai hari tidak bekerja:"
change_description: "Mengubah hari dalam seminggu yang dianggap hari bekerja atau hari tidak bekerja akan mempengaruhi hari mula dan selesai semua pakej kerja dalam semua projek dalam kejadian ini."
warning: >
Perubahan mungkin mengambil sedikit masa untuk berkesan. Anda akan dimaklumkan apabila semua pakej kerja yang berkaitan telah dikemas kini.
Adakah anda pasti anda ingin teruskan?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "pada"
@@ -365,9 +370,9 @@ ms:
new_features_html: >
Keluaran tersebut mengandungi pelbagai fitur baharu dan penambahbaikan:
eksport PDF paparan Gantt, cth. untuk mencetak (tambahan Enterprise)
Projek kegemaran
Bahagian dalam Mesyuarat
Paparkan mesyuarat di Halaman Saya dan halaman gambaran keseluruhan projek
Kemungkinan untuk sorokkan lampiran dalam tab Fail
Ruang tersuai jenis Pautan (URL)
ical_sharing_modal:
- title: "Langgan ke kalendar"
+ title: "Langgan kalendar"
inital_setup_error_message: "Ralat berlaku ketika sedang mengambil data."
- description: "Anda boleh menggunakan URL (iCalendar) untuk melanggan ke kalendar ini dalam pelanggan luaran dan lihat maklumat pakej kerja terkini dari situ."
+ description: "Anda boleh menggunakan URL (iCalendar) untuk melanggan kalendar ini dalam pelanggan luaran dan lihat maklumat pakej kerja terkini dari situ."
warning: "Sila jangan kongsi URL ini dengan pengguna lain. Sesiapa sahaja yang mempunyai pautan ini akan boleh melihat butiran pakej kerja tanpa akaun atau kata laluan."
token_name_label: "Dimanakah anda akan menggunakan ini?"
token_name_placeholder: 'Taip nama, cth. "Telefon"'
@@ -451,7 +456,7 @@ ms:
label_invalid: "Tidak sah"
label_import: "Import"
label_latest_activity: "Aktiviti terkini"
- label_last_updated_on: "Dikemas kini terakhir pada"
+ label_last_updated_on: "Kemas kini terakhir pada"
label_learn_more_link: "Ketahui lebih lanjut"
label_less_or_equal: "<="
label_less_than_ago: "kurang dari beberapa hari yang lalu"
@@ -562,8 +567,8 @@ ms:
label_rejected_files: "Fail-fail tersebut tidak dapat dimuat naik:"
label_rejected_files_reason: "Fail-fail tersebut tidak boleh dimuat naik kerana saiz mereka adalah lebih besar daripada %{maximumFilesize}"
label_wait: "Sila tunggu untuk konfigurasi..."
- label_upload_counter: "%{done} dari %{count} fail selesai"
- label_validation_error: "Pakej kerja tidak dapat disimpan kerana ralat berikut:"
+ label_upload_counter: "%{done} daripada %{count} fail selesai"
+ label_validation_error: "Pakej kerja tidak dapat disimpan disebabkan ralat berikut:"
label_version_plural: "Versi-versi"
label_view_has_changed: "Paparan ini mempunyai perubahan yang tidak disimpan. Klik untuk simpan mereka."
help_texts:
@@ -574,12 +579,12 @@ ms:
next: "Seterusnya"
got_it: "Faham"
steps:
- help_menu: "Menu Bantuan (?) menyediakan sumber bantuan tambahan. Di sini anda akan menjumpai panduan pengguna, video panduan membantu dan lebih lagi. Nikmati kerja anda di OpenProject!"
- members: "Jemput ahli baru untuk sertai projek anda."
- quick_add_button: "Klik pada ikon tambah (+) dalam navigasi pengepala untuk cipta projek baru atau untuk jemput rakan sekerja."
+ help_menu: "Menu Bantuan (?) menyediakan sumber bantuan tambahan. Di sini anda akan menjumpai panduan pengguna, video panduan dan lebih lagi. Nikmati kerja anda di OpenProject!"
+ members: "Jemput ahli baharu untuk sertai projek anda."
+ quick_add_button: "Klik ikon tambah (+) dalam navigasi pengepala untuk cipta projek baharu atau untuk jemput rakan sekerja."
sidebar_arrow: "Guna anak panah kembali di sudut kiri atas untuk kembali ke menu utama projek."
welcome: "Ambil lawatan pengenalan 3 minit untuk belajar fitur-fitur penting dengan banyak. Kami sarankan melengkapi langkah-langkah tersebut sehingga ke akhirnya. Anda boleh mula semula lawatan bila-bila masa."
- wiki: "Dalam wiki anda boleh mendokumentasikan dan kongsi pengetahuan bersama dengan pasukan anda."
+ wiki: "Dalam wiki anda boleh mendokumentasikan dan kongsi pengetahuan bersama pasukan anda."
backlogs:
overview: "Kendalikan kerja anda dalam paparan tunggakan."
sprints: "Di kanan anda mempunyai tunggakan produk dan tunggakan bug, di kiri anda mempunyai pecutan yang berkenaan. Di sini anda boleh mencipta epik, cerita pengguna, dan bug, utamakan dengan menarik & melepaskan dan tambah mereka ke pecutan."
@@ -1279,6 +1284,11 @@ ms:
placeholder: "Placeholder kini boleh digunakan dalam %{project}. Sementara itu anda sudah boleh merancang dengan pengguna tersebut dan tugaskan pakej kerja sebagai contoh."
group: "Kumpulan tersebut kini sebahagian daripada %{project}. Sementara itu anda sudah boleh merancang dengan kumpulan tersebut dan menugaskan pakej kerja sebagai contoh."
next_button: "Teruskan"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "Anda tiada projek kegemaran"
no_results_subtext: "Tambah satu atau beberapa projek sebagai kegemaran melalui gambaran keseluruhan mereka atau dalam senarai projek."
@@ -1339,7 +1349,7 @@ ms:
remove: "Keluarkan"
drop_modal:
focus_grab: "Ini adalah paksi fokus untuk modul. Tekan shift+tab untuk kembali ke elemen pencetus modul."
- Close: "Tutup"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Had Masa"
diff --git a/config/locales/crowdin/js-ne.yml b/config/locales/crowdin/js-ne.yml
index 81f1b07d9f1e..00ce390e2704 100644
--- a/config/locales/crowdin/js-ne.yml
+++ b/config/locales/crowdin/js-ne.yml
@@ -274,6 +274,11 @@ ne:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "on"
@@ -1282,6 +1287,11 @@ ne:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Continue"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1342,7 +1352,7 @@ ne:
remove: "Remove"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Close"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-nl.yml b/config/locales/crowdin/js-nl.yml
index e4dca2ff8080..20f8a2529eda 100644
--- a/config/locales/crowdin/js-nl.yml
+++ b/config/locales/crowdin/js-nl.yml
@@ -274,6 +274,11 @@ nl:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "op"
@@ -1282,6 +1287,11 @@ nl:
placeholder: "De tijdelijke gebruiker kan nu worden gebruikt in %{project}. Ondertussen kunt u deze gebruiker al plannen en werkpakketten toewijzen, bijvoorbeeld."
group: "De groep is nu een deel van %{project}. Ondertussen kun je al plannen maken met die groep en werkpakketten toewijzen, bijvoorbeeld."
next_button: "Ga verder"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1342,7 +1352,7 @@ nl:
remove: "Verwijder"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Sluiten"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-no.yml b/config/locales/crowdin/js-no.yml
index f6a935ef60ac..40b6ee3607c5 100644
--- a/config/locales/crowdin/js-no.yml
+++ b/config/locales/crowdin/js-no.yml
@@ -274,6 +274,11 @@
warning: >
Endringene kan ta noe tid på å bli effektivisert. Du vil bli varslet når alle relevante arbeidspakker har blitt oppdatert.
Er du sikker på at du vil fortsette?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "på"
@@ -1282,6 +1287,11 @@
placeholder: "Plassholderen kan nå brukes i %{project}. Samtidig kan du allerede planlegge med den brukeren og tilordne arbeidspakker i forekomsten."
group: "Gruppen er nå en del av %{project}. Dette betyr at du allerede kan planlegge med den gruppen og tildele arbeidspakker for forekomst."
next_button: "Fortsett"
+ exclusion_info:
+ modal:
+ title: "Status ekskludert fra hierarkiske summer"
+ content: >-
+ Statusen '%{status_name}' er konfigurert til å bli ekskludert fra hierarkiske summer av Arbeid, Gjenstående arbeid og % Ferdig. Summene tar ikke hensyn til denne verdien.
favorite_projects:
no_results: "Du har ingen favorittprosjekter"
no_results_subtext: "Legg til ett eller flere prosjekter som favoritt via oversikten eller i en prosjektliste."
@@ -1342,7 +1352,7 @@
remove: "Fjern"
drop_modal:
focus_grab: "Dette er et fokusanker for modaler. Trykk shift+tab for å gå tilbake til modal trigger elementet."
- Close: "Lukk"
+ close: "Lukk modal"
open_project_storage_modal:
waiting_title:
timeout: "Tidsavbrudd"
diff --git a/config/locales/crowdin/js-pl.yml b/config/locales/crowdin/js-pl.yml
index a3b021789807..3dae16f6d1e3 100644
--- a/config/locales/crowdin/js-pl.yml
+++ b/config/locales/crowdin/js-pl.yml
@@ -274,6 +274,11 @@ pl:
warning: >
Zmiany mogą wejść w życie po pewnym czasie. Gdy wszystkie odpowiednie pakiety robocze zostaną zaktualizowane, otrzymasz powiadomienie.
Czy na pewno chcesz kontynuować?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "wł"
@@ -1288,6 +1293,11 @@ pl:
placeholder: "Symbolu zastępczego można teraz użyć w %{project}. Tymczasem możesz już planować z tym użytkownikiem i na przykład przypisać pakiety robocze."
group: "Grupa jest teraz częścią %{project}. Tymczasem możesz już planować z tą grupą i na przykład przypisać pakiety robocze."
next_button: "Kontynuuj"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "Nie masz żadnych ulubionych projektów"
no_results_subtext: "Dodaj jeden lub wiele projektów jako ulubione w ich przeglądzie lub na liście projektów."
@@ -1348,7 +1358,7 @@ pl:
remove: "Usuń"
drop_modal:
focus_grab: "To jest kotwica fokusu okien modalnych. Naciśnij klawisze Shift+Tab, aby wrócić do elementu wyzwalającego okna modalne."
- Close: "Zamknij"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-pt-BR.yml b/config/locales/crowdin/js-pt-BR.yml
index 6907dceaca6a..e760427cd047 100644
--- a/config/locales/crowdin/js-pt-BR.yml
+++ b/config/locales/crowdin/js-pt-BR.yml
@@ -273,6 +273,11 @@ pt-BR:
warning: >
As alterações podem demorar algum tempo para entrar em vigor. Receberá uma notificação quando todos os pacotes de trabalho relevantes forem atualizados.
Tem a certeza de que deseja continuar?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "ligado"
@@ -1281,6 +1286,11 @@ pt-BR:
placeholder: "O espaço reservado agora pode ser usado em %{project}. Enquanto isso, você já pode planejar com este usuário e atribuir pacotes de trabalho por exemplo."
group: "O grupo agora faz parte de %{project}. Enquanto isso, você já pode planejar com este grupo e atribuir pacotes de trabalho por exemplo."
next_button: "Continuar"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "Você não possui projetos favoritos"
no_results_subtext: "Adicione um ou vários projetos como favoritos por meio de sua visão geral ou na lista de projetos."
@@ -1341,7 +1351,7 @@ pt-BR:
remove: "Remover"
drop_modal:
focus_grab: "Esta é uma âncora de foco para modais. Pressione Shift+tab para voltar ao elemento trigger modal."
- Close: "Fechar"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Tempo de espera"
diff --git a/config/locales/crowdin/js-pt-PT.yml b/config/locales/crowdin/js-pt-PT.yml
index 4f570bf08ce9..35a2d3aa77d3 100644
--- a/config/locales/crowdin/js-pt-PT.yml
+++ b/config/locales/crowdin/js-pt-PT.yml
@@ -274,6 +274,11 @@ pt-PT:
warning: >
As alterações podem demorar algum tempo a entrar em vigor. Receberá uma notificação quando todos os pacotes de trabalho relevantes forem atualizados.
Tem a certeza de que quer continuar?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "on"
@@ -1282,6 +1287,11 @@ pt-PT:
placeholder: "O espaço reservado agora pode ser usado em %{project}. Enquanto isso, já pode planear com este utilizador e atribuir pacotes de trabalho, por exemplo."
group: "O grupo agora faz parte de %{project}. Enquanto isso, já pode planear com este grupo e atribuir pacotes de trabalho, por exemplo."
next_button: "Continuar"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "Não tem projetos favoritos"
no_results_subtext: "Adicione um ou vários projetos como favoritos através da sua visão geral ou numa lista de projetos."
@@ -1342,7 +1352,7 @@ pt-PT:
remove: "Remover"
drop_modal:
focus_grab: "Esta é uma âncora de foco para modais. Pressione Shift+tab para voltar ao elemento de gatilho modal."
- Close: "Fechar"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Tempo esgotado"
diff --git a/config/locales/crowdin/js-ro.yml b/config/locales/crowdin/js-ro.yml
index a3b4b991ffdd..937aa3b60453 100644
--- a/config/locales/crowdin/js-ro.yml
+++ b/config/locales/crowdin/js-ro.yml
@@ -273,6 +273,11 @@ ro:
warning: >
Modificările ar putea dura ceva timp pentru a produce efecte. Vei fi notificat când toate pachetele de lucru relevante au fost actualizate.
Ești sigur că vrei să continui?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "pe"
@@ -1284,6 +1289,11 @@ ro:
placeholder: "Marca de poziție poate fi utilizată acum în %{project}. Între timp, puteți deja să planificați cu acel utilizator și să atribuiți pachete de lucru, de exemplu."
group: "Grupul este acum o parte din %{project}. Între timp, puteți deja să planificați cu acest grup și să atribuiți pachete de lucru, de exemplu."
next_button: "Continuaţi"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1344,7 +1354,7 @@ ro:
remove: "Eliminare"
drop_modal:
focus_grab: "Aceasta este o ancoră de focalizare pentru modalități. Apăsați shift+tab pentru a reveni la elementul de declanșare modal."
- Close: "Închide"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-ru.yml b/config/locales/crowdin/js-ru.yml
index f34b3412f30f..225deb25d762 100644
--- a/config/locales/crowdin/js-ru.yml
+++ b/config/locales/crowdin/js-ru.yml
@@ -273,6 +273,11 @@ ru:
warning: >
Для вступления изменений в силу может потребоваться некоторое время. Вы будете уведомлены, когда все соответствующие пакеты работ будут обновлены.
Хотите продолжить?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "вкл"
@@ -375,7 +380,7 @@ ru:
ical_generation_error_text: "Произошла ошибка при генерации URL-адреса календаря."
success_message: 'URL-адрес "%{name}" был успешно скопирован в ваш буфер обмена. Вставьте его в свой клиент календаря, чтобы завершить подписку.'
label_activate: "Активировать"
- label_assignee: "Ответственный"
+ label_assignee: "Назначенный"
label_add_column_after: "Добавить столбец после"
label_add_column_before: "Добавить столбец перед"
label_add_columns: "Добавить столбец"
@@ -612,7 +617,7 @@ ru:
mentioned: "упомянутый"
watched: "наблюдатель"
assigned: "назначенный"
- responsible: "подотчетный"
+ responsible: "ответственный"
created: "создано"
scheduled: "запланировано"
commented: "прокомментировано"
@@ -659,7 +664,7 @@ ru:
message: "Есть новые уведомления."
link_text: "Нажмите здесь, чтобы загрузить их."
menu:
- accountable: "Подотчетный"
+ accountable: "Ответственный"
by_project: "Непрочитано по проекту"
by_reason: "Причина"
inbox: "Входящие"
@@ -688,7 +693,7 @@ ru:
title: "Упомянутые"
description: "Получать уведомления каждый раз, когда кто-то упоминает меня"
assignee: "Назначенный"
- responsible: "Подотчетный"
+ responsible: "Ответственный"
shared: "Общий доступ"
watched: "Наблюдатель"
work_package_commented: "Все новые комментарии"
@@ -1287,6 +1292,11 @@ ru:
placeholder: "Теперь плейсхолдер может быть использован в %{project}. Тем временем вы уже можете планировать с этим пользователем и назначать рабочие пакеты."
group: "Теперь группа является частью %{project}. Тем временем вы уже можете спланировать работу с этой группой и назначить пакеты работ."
next_button: "Продолжить"
+ exclusion_info:
+ modal:
+ title: "Статус исключён из иерархии итогов"
+ content: >-
+ Статус '%{status_name}' был настроен на исключение из иерархии итогов Работы, Оставшейся работы и % завершения. Итоговые показатели не учитывают это значение.
favorite_projects:
no_results: "У вас нет избранных проектов"
no_results_subtext: "Добавьте один или несколько проектов в избранное через их обзор или в списке проектов."
@@ -1347,7 +1357,7 @@ ru:
remove: "Удалить"
drop_modal:
focus_grab: "Это якорь фокусировки для модальностей. Нажмите shift+ tab, чтобы вернуться к элементу модального триггера."
- Close: "Закрыть"
+ close: "Закрыть диалоговое окно"
open_project_storage_modal:
waiting_title:
timeout: "Время ожидания истекло"
diff --git a/config/locales/crowdin/js-rw.yml b/config/locales/crowdin/js-rw.yml
index 59fb6c1d802e..d82d03e07d61 100644
--- a/config/locales/crowdin/js-rw.yml
+++ b/config/locales/crowdin/js-rw.yml
@@ -274,6 +274,11 @@ rw:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "on"
@@ -1282,6 +1287,11 @@ rw:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Continue"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1342,7 +1352,7 @@ rw:
remove: "Remove"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Close"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-si.yml b/config/locales/crowdin/js-si.yml
index 050d86d3cee9..95f1e050c165 100644
--- a/config/locales/crowdin/js-si.yml
+++ b/config/locales/crowdin/js-si.yml
@@ -274,6 +274,11 @@ si:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "මත"
@@ -1282,6 +1287,11 @@ si:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "ඉදිරියට යන්න"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1342,7 +1352,7 @@ si:
remove: "ඉවත් කරන්න"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "වසන්න"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-sk.yml b/config/locales/crowdin/js-sk.yml
index c87696d92383..fc048453d3e8 100644
--- a/config/locales/crowdin/js-sk.yml
+++ b/config/locales/crowdin/js-sk.yml
@@ -274,6 +274,11 @@ sk:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "dňa"
@@ -1288,6 +1293,11 @@ sk:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Pokračovať"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1348,7 +1358,7 @@ sk:
remove: "Vymazať"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Zatvoriť"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-sl.yml b/config/locales/crowdin/js-sl.yml
index 5cd2f952e5f2..48ec63af3779 100644
--- a/config/locales/crowdin/js-sl.yml
+++ b/config/locales/crowdin/js-sl.yml
@@ -273,6 +273,11 @@ sl:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "vključeno"
@@ -1287,6 +1292,11 @@ sl:
placeholder: "Rezervirano mesto se zdaj lahko uporabi v %{project}. Medtem lahko planirate s tem uporabnikom in mu dodelite delovne naloge."
group: "Skupina je zdaj del %{project}. Medtem lahko planirate s to skupino in ji dodelite delovne naloge."
next_button: "Nadaljuj"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1347,7 +1357,7 @@ sl:
remove: "Odstrani"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Zapri"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-sr.yml b/config/locales/crowdin/js-sr.yml
index 81efcac5d7e1..c00dd6c7b2a0 100644
--- a/config/locales/crowdin/js-sr.yml
+++ b/config/locales/crowdin/js-sr.yml
@@ -274,6 +274,11 @@ sr:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "on"
@@ -1285,6 +1290,11 @@ sr:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Continue"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1345,7 +1355,7 @@ sr:
remove: "Remove"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Zatvori"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-sv.yml b/config/locales/crowdin/js-sv.yml
index 04eea082da36..67d3cbd57ea7 100644
--- a/config/locales/crowdin/js-sv.yml
+++ b/config/locales/crowdin/js-sv.yml
@@ -273,6 +273,11 @@ sv:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "på"
@@ -1281,6 +1286,11 @@ sv:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Fortsätt"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1341,7 +1351,7 @@ sv:
remove: "Ta bort"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Stäng"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-th.yml b/config/locales/crowdin/js-th.yml
index 770c131b56fd..d48c8db3abab 100644
--- a/config/locales/crowdin/js-th.yml
+++ b/config/locales/crowdin/js-th.yml
@@ -274,6 +274,11 @@ th:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "on"
@@ -1279,6 +1284,11 @@ th:
placeholder: "ขณะนี้ Placeholder สามารถใช้งานใน %{project} ได้แล้ว, คุณสามารถวางแผนกับผู้ใช้รายนั้นและกำหนดแพ็คเกจงานได้"
group: "ตอนนี้กลุ่มนี้เป็นส่วนหนึ่งของ %{project}, คุณสามารถวางแผนกับกลุ่มนั้นและกำหนดแพ็คเกจงานได้"
next_button: "Continue"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1339,7 +1349,7 @@ th:
remove: "Remove"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Close"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-tr.yml b/config/locales/crowdin/js-tr.yml
index f2352341bbb5..9c4b64897a38 100644
--- a/config/locales/crowdin/js-tr.yml
+++ b/config/locales/crowdin/js-tr.yml
@@ -273,6 +273,11 @@ tr:
change_description: "Haftanın hangi günlerinin iş günü olarak kabul edileceğini değiştirmek, bu durumda tüm projelerdeki tüm iş paketlerinin başlangıç ve bitiş günlerini etkileyebilir."
warning: >
Değişikliklerin geçerlilik kazanması biraz zaman alabilir. İlgili tüm iş paketleri güncellendiğinde bilgilendirileceksiniz. Devam etmek istediğine emin misin?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "açık"
@@ -1281,6 +1286,11 @@ tr:
placeholder: "Kullanıcı artık %{project} 'e erişmek için oturum açabilir. Bu arada, o kullanıcıyla zaten plan yapabilir ve örneğin iş paketleri atayabilirsiniz."
group: "Grup artık %{project} 'nin bir parçası. Bu arada, bu grupla zaten plan yapabilir ve örneğin iş paketleri atayabilirsiniz."
next_button: "Devam et"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1341,7 +1351,7 @@ tr:
remove: "Kaldır"
drop_modal:
focus_grab: "Bu, modallar için bir odak noktasıdır. Modal tetikleme öğesine geri dönmek için shift+tab tuşlarına basın."
- Close: "Kapat"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-uk.yml b/config/locales/crowdin/js-uk.yml
index e8f1679a0ad0..596357093a93 100644
--- a/config/locales/crowdin/js-uk.yml
+++ b/config/locales/crowdin/js-uk.yml
@@ -274,6 +274,11 @@ uk:
warning: >
Застосування змін може тривати деякий час. Ви отримаєте сповіщення, коли всі відповідні пакети робіт буде оновлено.
Продовжити?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "на"
@@ -1288,6 +1293,11 @@ uk:
placeholder: "Прототип тепер може ввійти, щоб отримати доступ до проєкту «%{project}». Тим часом ви вже можете включати цього користувача в план і призначати йому пакети робіт."
group: "Ця група тепер входить у проєкт «%{project}». Тим часом ви вже можете включати її в план і призначати їй пакети робіт."
next_button: "Продовжити"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "У вас немає обраних проєктів"
no_results_subtext: "Додайте один або кілька проєктів в обране на відповідній сторінці огляду або в списку проєктів."
@@ -1348,7 +1358,7 @@ uk:
remove: "Видалити"
drop_modal:
focus_grab: "Це якір фокуса для модальних вікон. Натисніть клавіші Shift + Tab, щоб повернутися до тригера модального вікна."
- Close: "Закрити"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-uz.yml b/config/locales/crowdin/js-uz.yml
index b359afd4f165..63ca003fa244 100644
--- a/config/locales/crowdin/js-uz.yml
+++ b/config/locales/crowdin/js-uz.yml
@@ -274,6 +274,11 @@ uz:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "on"
@@ -1282,6 +1287,11 @@ uz:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Continue"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1342,7 +1352,7 @@ uz:
remove: "Remove"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Close"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-vi.yml b/config/locales/crowdin/js-vi.yml
index eb0cba981648..e876c63f7e01 100644
--- a/config/locales/crowdin/js-vi.yml
+++ b/config/locales/crowdin/js-vi.yml
@@ -273,6 +273,11 @@ vi:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "lúc"
@@ -1278,6 +1283,11 @@ vi:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "Nhóm này hiện là một phần của %{project}. Trong khi đó, bạn có thể lên kế hoạch cho nhóm đó và chỉ định các gói làm việc cho từng trường hợp."
next_button: "Tiếp tục"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1338,7 +1348,7 @@ vi:
remove: "Xoá"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Đóng"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/js-zh-CN.yml b/config/locales/crowdin/js-zh-CN.yml
index f862785208d3..3b0b304bef78 100644
--- a/config/locales/crowdin/js-zh-CN.yml
+++ b/config/locales/crowdin/js-zh-CN.yml
@@ -273,6 +273,11 @@ zh-CN:
change_description: "更改一周中哪些天被视为工作日或非工作日可能会影响此实例中所有项目中所有工作包的开始和结束日期。"
warning: >
更改可能需要一些时间才能生效。当更新完所有相关工作包时,您将收到通知。
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "于"
@@ -1278,6 +1283,11 @@ zh-CN:
placeholder: "现在可以在 %{project} 中使用占位符。同时,您已经可以与该用户一起制定计划并分配工作包等。"
group: "该组现已加入 %{project}。同时,您已经可以与该组一起制定计划并分配工作包等。"
next_button: "继续"
+ exclusion_info:
+ modal:
+ title: "从层次结构总计中排除的状态"
+ content: >-
+ 状态 "%{status_name}"已被配置为排除在 "工时"、"剩余工时 "和 "完成百分比 "的层次结构总计中。总计不考虑该值。
favorite_projects:
no_results: "您没有收藏的项目"
no_results_subtext: "通过项目概览或项目列表添加一个或多个项目作为收藏夹。"
@@ -1338,12 +1348,12 @@ zh-CN:
remove: "移除"
drop_modal:
focus_grab: "该信息是模态框的焦点锚点。按 Shift+Tab 可以返回到模态框的触发元素。"
- Close: "关闭"
+ close: "关闭模式"
open_project_storage_modal:
waiting_title:
- timeout: "Timeout"
+ timeout: "超时"
waiting_subtitle:
network_off: "网络有问题。"
network_on: "网络已恢复。我们正在努力。"
timeout: >
- OpenProject could not provide you access to the project folder within the expected period of time. Please, try once again.
If that problem persists please contact you OpenProject administrator to check the health status of the file storage setup.
+ OpenProject无法让您在预期时间内访问项目文件夹。请再试一次。
如果问题仍然存在,请联系OpenProject管理员检查文件存储设置的运行状况。
diff --git a/config/locales/crowdin/js-zh-TW.yml b/config/locales/crowdin/js-zh-TW.yml
index 424dc0d4fdfe..1cd8ec4a7c23 100644
--- a/config/locales/crowdin/js-zh-TW.yml
+++ b/config/locales/crowdin/js-zh-TW.yml
@@ -273,6 +273,11 @@ zh-TW:
warning: >
The changes might take some time to take effect. You will be notified when all relevant work packages have been updated.
Are you sure you want to continue?
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make % Complete a non-editable field whose value is derived from Work and Remaining work. Existing values for % Complete are preserved. If values for Work and Remaining work were not present, they will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result in all existing % Complete values to be lost and replaced with values associated with each status. Existing values for Remaining work may also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "開啟"
@@ -1278,6 +1283,11 @@ zh-TW:
placeholder: "The placeholder can now be used in %{project}. Meanwhile you can already plan with that user and assign work packages for instance."
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "繼續"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy totals of Work, Remaining work, and % Complete. The totals do not take this value into account.
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1338,7 +1348,7 @@ zh-TW:
remove: "刪除"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "關閉"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/locales/crowdin/ka.yml b/config/locales/crowdin/ka.yml
index 75ae15aafd34..e50eac593044 100644
--- a/config/locales/crowdin/ka.yml
+++ b/config/locales/crowdin/ka.yml
@@ -300,6 +300,12 @@ ka:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: There are currently no types available.
form:
@@ -448,12 +454,20 @@ ka:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: There are currently no work package statuses.
no_results_content_text: Add a new status
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "ღია"
light_high_contrast: "Light high contrast"
@@ -623,6 +637,7 @@ ka:
status:
is_closed: "Work package closed"
is_readonly: "Work package read-only"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "შენიშვნები"
member:
@@ -959,6 +974,14 @@ ka:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1143,18 +1166,6 @@ ka:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "რეგისტრაციის მიზეზი"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "ცვლილებები"
message: "ფორუმები"
@@ -1605,6 +1616,12 @@ ka:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: სთ
days: დ
@@ -1658,7 +1675,7 @@ ka:
dates_changed: "თარიღები შეიცვალა"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1675,8 +1692,9 @@ ka:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2333,7 +2351,7 @@ ka:
label_workflow: "სამუშაო პროცესი"
label_workflow_plural: "სამუშაო პროცესები"
label_workflow_summary: "შეჯამება"
- label_working_days: "სამუშაო დღეები"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 დახურულია"
other: "%{count} closed"
@@ -2933,6 +2951,9 @@ ka:
setting_cross_project_work_package_relations: "Allow cross-project work package relations"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "თარიღი"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Default language"
setting_default_projects_modules: "Default enabled modules for new projects"
setting_default_projects_public: "New projects are public by default"
@@ -2948,6 +2969,12 @@ ka:
setting_feeds_limit: "Feed content limit"
setting_file_max_size_displayed: "Max size of text files displayed inline"
setting_host_name: "ჰოსტის სახელი"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3389,12 +3416,12 @@ ka:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/kk.yml b/config/locales/crowdin/kk.yml
index cfaa17d43140..4b35fd9f7503 100644
--- a/config/locales/crowdin/kk.yml
+++ b/config/locales/crowdin/kk.yml
@@ -300,6 +300,12 @@ kk:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: There are currently no types available.
form:
@@ -448,12 +454,20 @@ kk:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: There are currently no work package statuses.
no_results_content_text: Add a new status
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -623,6 +637,7 @@ kk:
status:
is_closed: "Work package closed"
is_readonly: "Work package read-only"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Notes"
member:
@@ -959,6 +974,14 @@ kk:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1143,18 +1166,6 @@ kk:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Changesets"
message: "Forums"
@@ -1605,6 +1616,12 @@ kk:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1658,7 +1675,7 @@ kk:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1675,8 +1692,9 @@ kk:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2333,7 +2351,7 @@ kk:
label_workflow: "Workflow"
label_workflow_plural: "Workflows"
label_workflow_summary: "Summary"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 closed"
other: "%{count} closed"
@@ -2933,6 +2951,9 @@ kk:
setting_cross_project_work_package_relations: "Allow cross-project work package relations"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "Date"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Default language"
setting_default_projects_modules: "Default enabled modules for new projects"
setting_default_projects_public: "New projects are public by default"
@@ -2948,6 +2969,12 @@ kk:
setting_feeds_limit: "Feed content limit"
setting_file_max_size_displayed: "Max size of text files displayed inline"
setting_host_name: "Host name"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3389,12 +3416,12 @@ kk:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/ko.yml b/config/locales/crowdin/ko.yml
index e4e05966b7ac..481d7836ac00 100644
--- a/config/locales/crowdin/ko.yml
+++ b/config/locales/crowdin/ko.yml
@@ -300,6 +300,12 @@ ko:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: 사용 가능한 타입이 없습니다.
form:
@@ -441,12 +447,20 @@ ko:
이 상태를 읽기 전용으로 작업 패키지에 표시하려면 이 옵션을 선택합니다. 상태를 제외하고 특성은 변경할 수 없습니다.
참고: 상속된 값(예: 자식 또는 관계)은 계속 적용됩니다.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
이 상태 색상을 할당하거나 변경하려면 클릭하세요.
상태 버튼에 표시되고 테이블의 작업 패키지를 강조 표시하는 데 사용할 수 있습니다.
index:
no_results_title_text: 작업 패키지 상태가 없습니다.
no_results_content_text: 새 상태 추가
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "라이트"
light_high_contrast: "라이트 하이 콘트라스트"
@@ -615,6 +629,7 @@ ko:
status:
is_closed: "종료된 작업 패키지"
is_readonly: "읽기 전용 작업 패키지"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "노트"
member:
@@ -951,6 +966,14 @@ ko:
base:
working_days_are_missing: "적어도 일주일의 하루는 근무일로 정의해야 합니다."
previous_working_day_changes_unprocessed: "근무일 구성에 대한 이전 변경 사항이 아직 적용되지 않았습니다."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1127,18 +1150,6 @@ ko:
other: "%{count}시간"
updated: "%{old_value}에서 %{value}(으)로 변경됨"
logged_for: "기록함 -"
- meeting_agenda_item:
- duration:
- added: "%{value}(으)로 설정됨"
- added_html: "%{value}(으)로 설정됨"
- removed: "제거됨"
- updated: "%{old_value}에서 %{value}(으)로 변경됨"
- updated_html: "%{old_value}에서 %{value}(으)로 변경됨"
- position:
- updated: "재정렬됨"
- work_package:
- updated: "%{old_value}에서 %{value}(으)로 변경됨"
- updated_html: "%{old_value}에서 %{value}(으)로 변경됨"
filter:
changeset: "변경 집합"
message: "포럼"
@@ -1571,6 +1582,12 @@ ko:
pdf_gantt: "PDF Gantt"
image:
omitted: "이미지를 내보내지 못했습니다."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: 시간
days: 일
@@ -1624,7 +1641,7 @@ ko:
dates_changed: "변경된 날짜"
default_attribute_written: "읽기 전용 특성 작성됨"
progress_mode_changed_to_status_based: "진행률 계산 업데이트됨"
- status_p_complete_changed: "상태 완료 % 변경됨"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject 시스템 업데이트:"
cause_descriptions:
work_package_predecessor_changed_times: 이전 %{link}에 대한 변경 사항 기준
@@ -1641,8 +1658,9 @@ ko:
working: "%{date}은(는) 이제 근무일입니다."
non_working: "%{date}은(는) 이제 휴무일입니다."
progress_mode_changed_to_status_based: 진행률 계산 모드가 상태 기반으로 설정되었습니다
- status_p_complete_changed: >-
- 상태 '%{status_name}'의 완료 % 값이 %{old_value}%에서 %{new_value}%(으)로 변경되었습니다
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
지금부터 파일 링크(외부 저장소에 저장된 파일)와 관련된 활동이 활동 탭에 표시됩니다. 다음은 이미 존재하는 링크와 관련된 활동을 나타냅니다.
@@ -2299,7 +2317,7 @@ ko:
label_workflow: "워크플로"
label_workflow_plural: "워크플로"
label_workflow_summary: "요약"
- label_working_days: "근무일"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1개 닫힘"
other: "%{count}개 닫힘"
@@ -2894,6 +2912,9 @@ ko:
setting_cross_project_work_package_relations: "교차 프로젝트 작업 패키지 관계 허용"
setting_first_week_of_year: "1년의 첫 주 기준"
setting_date_format: "날짜"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "기본 언어"
setting_default_projects_modules: "새 프로젝트에 대해 기본적으로 활성화된 모듈"
setting_default_projects_public: "새 프로젝트는 기본적으로 공용입니다."
@@ -2909,6 +2930,12 @@ ko:
setting_feeds_limit: "피드 콘텐츠 제한"
setting_file_max_size_displayed: "인라인에 표시되는 텍스트 파일의 최대 크기"
setting_host_name: "호스트 이름"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "활성화 이메일 만료 기간:"
setting_work_package_done_ratio: "진행률 계산"
setting_work_package_done_ratio_field: "작업 기반"
@@ -3349,12 +3376,12 @@ ko:
additional_privileges_project_or_group: "(프로젝트 또는 그룹 멤버로서) 추가적인 권한을 가질 수 있습니다"
working_days:
info: >
- 선택하지 않은 요일은 작업 패키지를 예약할 때 건너뜁니다(일 수에 포함되지 않음). 작업 패키지 수준에서 재정의할 수 있습니다.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
아래 목록에 추가된 날짜는 휴무로 간주되며 작업 패키지를 예약할 때 건너뜁니다.
change_button: "근무일 변경"
warning: >
- 근무일 또는 휴무일로 간주되는 요일을 변경하면 이 인스턴스의 모든 프로젝트에 있는 모든 작업 패키지의 시작 날짜 및 완료 날짜에 영향을 미칠 수 있습니다. 변경 사항 적용 버튼을 클릭한 후에만 변경 사항이 적용됩니다.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**근무일**이 변경되었습니다(%{changes})._
days:
diff --git a/config/locales/crowdin/lt.yml b/config/locales/crowdin/lt.yml
index 1c9a07f25e15..f0100301db00 100644
--- a/config/locales/crowdin/lt.yml
+++ b/config/locales/crowdin/lt.yml
@@ -297,6 +297,12 @@ lt:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Nėra prieinamų tipų.
form:
@@ -457,12 +463,20 @@ lt:
Nebebus galima keisti jokių atributų išskyrus būseną.
Pastaba: paveldėti atributai (pvz., iš vaikų ar sąryšių) gali būti keičiami automatiškai.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Spauskite, kad priskirtumėte arba pakeistumėte šios būsenos spalvą.
Ji rodoma būsenos mygtuke arba gali būti naudojama paryškinti darbo paketus lentelėje.
index:
no_results_title_text: Nėra jokių darbų paketo būsenų.
no_results_content_text: Pridėti naują būseną
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Šviesi"
light_high_contrast: "Šviesi kontrastinga"
@@ -634,6 +648,7 @@ lt:
status:
is_closed: "Darbų paketas uždarytas"
is_readonly: "Darbų paketas nekeičiamas"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Pastabos"
member:
@@ -970,6 +985,14 @@ lt:
base:
working_days_are_missing: "Bent viena diena savaitėje turi būti apibrėžta kaip darbo diena."
previous_working_day_changes_unprocessed: "Ankstesni darbo dienų konfigūracijos pakeitimai dar nebuvo pritaikyti."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1170,18 +1193,6 @@ lt:
other: "%{count} valandos"
updated: "pakeitė iš %{old_value} į %{value}"
logged_for: "Registruota"
- meeting_agenda_item:
- duration:
- added: "nustatyti %{value}"
- added_html: "nustatyti %{value}"
- removed: "išimta"
- updated: "pakeitė iš %{old_value} į %{value}"
- updated_html: "pakeista iš %{old_value} į %{value}"
- position:
- updated: "perrikiuota"
- work_package:
- updated: "pakeista iš %{old_value} į %{value}"
- updated_html: "pakeista iš %{old_value} į %{value}"
filter:
changeset: "Pakeitimų paketai"
message: "Forumai"
@@ -1668,6 +1679,12 @@ lt:
pdf_gantt: "PDF Gantt"
image:
omitted: "Paveiksliukas neeksportuotas."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1721,7 +1738,7 @@ lt:
dates_changed: "Datos pasikeitė"
default_attribute_written: "Tik-skaitymo atributai įrašyti"
progress_mode_changed_to_status_based: "Eigos skaičiavimas atnaujintas"
- status_p_complete_changed: "Būsenos % baigta pakeista"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject sistemos atnaujinimas"
cause_descriptions:
work_package_predecessor_changed_times: dėl pirmtako pakeitimų %{link}
@@ -1738,8 +1755,9 @@ lt:
working: "%{date} dabar yra darbo"
non_working: "%{date} dabar yra nedarbo"
progress_mode_changed_to_status_based: Nustatytas eigos skaičiavimo režimas priklausantis-nuo-būsenos
- status_p_complete_changed: >-
- % baigta reikšmė būsenai „%{status_name}“ pakeista iš %{old_value}% į %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
Nuo dabar, su failų nuorodomis (failais, saugomais išorinse saugyklose) susiję veiksmai bus rodomi Veiksmų kortelėje. Žemiau pateikiamas jau egzistavusių nuorodų veiksmų sąrašas:
@@ -2396,7 +2414,7 @@ lt:
label_workflow: "Darbų eiga"
label_workflow_plural: "Darbų eigos"
label_workflow_summary: "Santrauka"
- label_working_days: "Darbo dienos"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 uždarytas"
other: "%{count} uždaryti (-as, -ų)"
@@ -2996,6 +3014,9 @@ lt:
setting_cross_project_work_package_relations: "Leisti tarp-projektinius darbų paketo ryšius"
setting_first_week_of_year: "Pirma metų savaitė turi"
setting_date_format: "Data"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Numatytoji kalba"
setting_default_projects_modules: "Pagal nutylėjimą naujame projekte įjungti moduliai"
setting_default_projects_public: "Nauji projektai yra vieši pagal nutylėjimą"
@@ -3011,6 +3032,12 @@ lt:
setting_feeds_limit: "Naujienų kanalų turinio limitas"
setting_file_max_size_displayed: "Maksimalus tekstinių failų dydis rodomas vienoje eilutėje"
setting_host_name: "Serverio vardas"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Aktyvavimo laiško galiojimas baigiasi po"
setting_work_package_done_ratio: "Eigos skaičiavimas"
setting_work_package_done_ratio_field: "Pagal-darbą"
@@ -3453,12 +3480,12 @@ lt:
additional_privileges_project_or_group: "Gali turėti papildomų privilegijų (kaip projekto ar grupės narys)"
working_days:
info: >
- Nepažymėtos dienos praleidžiamos skaičiuojant darbo paketus (ir neįtraukiamos į dienų skaičių). Šituos nustatymus galima permušti darbo paketo lygyje.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Į žemiau esantį sąrašą pridėtos datos laikomos nedarbo dienomis ir praleidžiamos planuojant darbo paketus.
change_button: "Keisti darbo dienas"
warning: >
- Keičiant dienas, kurios yra darbo ar nedarbo dienos, gali keistis visų projektų darbo paketų pradžios ir pabaigos dienos. Prašome atkreipti dėmesį, kad pakeitimai pritaikomi tik po to, kai jūs paspaudžiate mygtuką pritaikyti.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Darbo dienos** pakeistos (%{changes})._
days:
diff --git a/config/locales/crowdin/lv.yml b/config/locales/crowdin/lv.yml
index 968cce9c79cb..3809b9d7ed44 100644
--- a/config/locales/crowdin/lv.yml
+++ b/config/locales/crowdin/lv.yml
@@ -300,6 +300,12 @@ lv:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Pašlaik nav pieejams neviens veids.
form:
@@ -454,12 +460,20 @@ lv:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: Pašlaik nav nevienas darba pakas statuss.
no_results_content_text: Pievienot jaunu statusu
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -630,6 +644,7 @@ lv:
status:
is_closed: "Aizvērtie pieteikuma tipi"
is_readonly: "Work package read-only"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Piezīmes"
member:
@@ -966,6 +981,14 @@ lv:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1158,18 +1181,6 @@ lv:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Changesets"
message: "Forums"
@@ -1638,6 +1649,12 @@ lv:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1691,7 +1708,7 @@ lv:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1708,8 +1725,9 @@ lv:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2366,7 +2384,7 @@ lv:
label_workflow: "Darbplūsma"
label_workflow_plural: "Workflows"
label_workflow_summary: "Kopsavilkums"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 slēgts"
other: "%{count} slēgti"
@@ -2968,6 +2986,9 @@ lv:
setting_cross_project_work_package_relations: "Allow cross-project work package relations"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "Datums"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Default language"
setting_default_projects_modules: "Pēc noklusējuma aktivizētie moduļi jauniem projektiem"
setting_default_projects_public: "New projects are public by default"
@@ -2983,6 +3004,12 @@ lv:
setting_feeds_limit: "Feed content limit"
setting_file_max_size_displayed: "Max size of text files displayed inline"
setting_host_name: "Host name"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3425,12 +3452,12 @@ lv:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/mn.yml b/config/locales/crowdin/mn.yml
index 8c4dffbfdc37..0a18aed74724 100644
--- a/config/locales/crowdin/mn.yml
+++ b/config/locales/crowdin/mn.yml
@@ -300,6 +300,12 @@ mn:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: There are currently no types available.
form:
@@ -448,12 +454,20 @@ mn:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: There are currently no work package statuses.
no_results_content_text: Add a new status
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -623,6 +637,7 @@ mn:
status:
is_closed: "Work package closed"
is_readonly: "Work package read-only"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Notes"
member:
@@ -959,6 +974,14 @@ mn:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1143,18 +1166,6 @@ mn:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Changesets"
message: "Forums"
@@ -1605,6 +1616,12 @@ mn:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1658,7 +1675,7 @@ mn:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1675,8 +1692,9 @@ mn:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2333,7 +2351,7 @@ mn:
label_workflow: "Workflow"
label_workflow_plural: "Workflows"
label_workflow_summary: "Summary"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 closed"
other: "%{count} closed"
@@ -2933,6 +2951,9 @@ mn:
setting_cross_project_work_package_relations: "Allow cross-project work package relations"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "Date"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Default language"
setting_default_projects_modules: "Default enabled modules for new projects"
setting_default_projects_public: "New projects are public by default"
@@ -2948,6 +2969,12 @@ mn:
setting_feeds_limit: "Feed content limit"
setting_file_max_size_displayed: "Max size of text files displayed inline"
setting_host_name: "Host name"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3389,12 +3416,12 @@ mn:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/ms.yml b/config/locales/crowdin/ms.yml
index fa8417ce41da..6c8dbf133d7e 100644
--- a/config/locales/crowdin/ms.yml
+++ b/config/locales/crowdin/ms.yml
@@ -299,6 +299,12 @@ ms:
is_required_blank_slate:
heading: Diperlukan dalam semua projek
description: Atribut projek ini telah diaktifkan dalam semua projek sejak pilihan "Diperlukan dalam semua projek" telah ditandakan. Ia tidak boleh dinyahaktifkan untuk projek individu.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Tiada jenis yang tersedia buat masa ini.
form:
@@ -441,12 +447,19 @@ ms:
Tiada atribut yang boleh diubah dengan pengecualian status.
Perhatian: Nilai yang diwarisi (cth, dari anak-anak atau saudara) masih akan digunakan.
+ status_excluded_from_totals_text: |-
+ Tandakan pilihan ini untuk mengecualikan pakej kerja dengan status ini dari jumlah Kerja, Kerja yang berbaki, dan % Selesai dalam hierarki.
status_color_text: |
Klik untuk menugaskan atau menukar warna status ini.
Ia ditunjukkan pada butang status dan boleh digunakan untuk menyoroti pakej kerja dalam jadual.
index:
no_results_title_text: Tiada status pakej kerja buat masa ini.
no_results_content_text: Tambah status baharu
+ headers:
+ is_default: "Default"
+ is_closed: "Tertutup"
+ is_readonly: "Baca-sahaja"
+ excluded_from_totals: "Dikecualikan daripada jumlah"
themes:
light: "Terang"
light_high_contrast: "Kontras tinggi yang terang"
@@ -615,6 +628,7 @@ ms:
status:
is_closed: "Pakej kerja ditutup"
is_readonly: "Pakej kerja baca-sahaja"
+ excluded_from_totals: "Dikecualikan daripada pengiraan jumlah dalam hierarki"
journal:
notes: "Nota"
member:
@@ -951,6 +965,14 @@ ms:
base:
working_days_are_missing: "Sekurang-kurangnya sehari dalam seminggu perlu ditentukan sebagai hari bekerja."
previous_working_day_changes_unprocessed: "Perubahan terdahulu pada konfigurasi hari bekerja belum dilaksanakan lagi."
+ hours_per_day_are_missing: "Bilangan jam dalam sehari perlu ditentukan."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1127,18 +1149,6 @@ ms:
other: "%{count} jam"
updated: "ditukar dari %{old_value} kepada %{value}"
logged_for: "Dilog untuk"
- meeting_agenda_item:
- duration:
- added: "ditetapkan kepada %{value}"
- added_html: "ditetapkan kepada %{value}"
- removed: "dikeluarkan"
- updated: "ditukar dari %{old_value} kepada %{value}"
- updated_html: "ditukar dari %{old_value} kepada %{value}"
- position:
- updated: "disusun semula"
- work_package:
- updated: "ditukar dari %{old_value} kepada %{value}"
- updated_html: "ditukar dari %{old_value} kepada %{value}"
filter:
changeset: "Set ubah suai"
message: "Forum-forum"
@@ -1571,6 +1581,12 @@ ms:
pdf_gantt: "Gantt PDF"
image:
omitted: "Imej tidak dieksport."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: j
days: h
@@ -1624,7 +1640,7 @@ ms:
dates_changed: "Tarikh ditukar"
default_attribute_written: "Atribut baca-sahaja ditulis"
progress_mode_changed_to_status_based: "Pengiraan perkembangan dikemas kini"
- status_p_complete_changed: "Status % Selesai diubah"
+ status_changed: "Status '%{status_name}'"
system_update: "Kemas kini sistem OpenProject:"
cause_descriptions:
work_package_predecessor_changed_times: dengan perubahan pada pendahulu %{link}
@@ -1641,8 +1657,9 @@ ms:
working: "%{date} kini hari bekerja"
non_working: "%{date} kini bukan hari bekerja"
progress_mode_changed_to_status_based: Mod pengiraan perkembangan ditetapkan kepada berasaskan status
- status_p_complete_changed: >-
- % nilai selesai untuk status '%{status_name}' diubah dari %{old_value}% kepada %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
Mulai sekarang, aktiviti berkaitan dengan pautan fail (fail-fail yang disimpan di storan luaran) akan muncul dalam tab Aktiviti. Yang berikut mewakili aktiviti berkenaan pautan yang sudah sedia ada:
@@ -2299,7 +2316,7 @@ ms:
label_workflow: "Aliran kerja"
label_workflow_plural: "Aliran kerja"
label_workflow_summary: "Ringkasan"
- label_working_days: "Hari bekerja"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 ditutup"
other: "%{count} ditutup"
@@ -2895,6 +2912,9 @@ ms:
setting_cross_project_work_package_relations: "Benarkan hubungan pakej kerja rentas projek"
setting_first_week_of_year: "Minggu pertama dalam tahun mengandungi "
setting_date_format: "Tarikh"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Bahasa default"
setting_default_projects_modules: "Modul yang diaktifkan secara default untuk projek baharu"
setting_default_projects_public: "Projek baharu adalah awam secara default"
@@ -2910,6 +2930,12 @@ ms:
setting_feeds_limit: "Had kandungan feed "
setting_file_max_size_displayed: "Saiz maksimum fail teks ditampilkan sebaris "
setting_host_name: "Nama hos"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Pengaktifan e-mel tamat tempoh selepas"
setting_work_package_done_ratio: "Pengiraan perkembangan"
setting_work_package_done_ratio_field: "Berasaskan kerja"
@@ -3113,10 +3139,10 @@ ms:
text_hours_between: "Antara %{min} dan %{max} jam."
text_work_package_added: "Pakej kerja %{id} telah dilaporkan oleh %{author}."
text_work_package_category_destroy_assignments: "Padam kategori tugasan"
- text_work_package_category_destroy_question: "Beberapa pakej kerja (%{count}) ditugaskan untuk kategori ini. Apakah yang anda ingin lakukan?"
+ text_work_package_category_destroy_question: "Beberapa pakej kerja (%{count}) ditugaskan bagi kategori ini. Apakah yang anda ingin lakukan?"
text_work_package_category_reassign_to: "Tetapkan semula pakej kerja ke kategori ini"
text_work_package_updated: "Pakej kerja %{id} telah dikemas kini oleh %{author}."
- text_work_package_watcher_added: "Anda telah ditambah sebagai pemerhati untuk Pakej kerja %{id} oleh %{watcher_changer}."
+ text_work_package_watcher_added: "Anda telah ditambah sebagai pemerhati bagi Pakej kerja %{id} oleh %{watcher_changer}."
text_work_package_watcher_removed: "Anda telah dikeluarkan dari pemerhati Pakej kerja %{id} oleh %{watcher_changer}."
text_work_packages_destroy_confirmation: "Adakah anda pasti anda ingin memadam pakej kerja yang dipilih tersebut?"
text_work_packages_ref_in_commit_messages: "Merujuk dan memperbaiki pakej kerja dalam mesej kommit"
@@ -3142,7 +3168,7 @@ ms:
text_min_max_length_info: "0 bermakna tiada had"
text_no_roles_defined: Tiada peranan ditentukan.
text_no_access_tokens_configurable: "Tiada token akses yang boleh dikonfigurasikan."
- text_no_configuration_data: "Peranan, jenis, status pakej kerja dan aliran kerja belum dikonfigurasikan lagi. Sangat disarankan untuk memuatkan konfigurasi default. Anda akan dapat mengubahnya selepas dimuatkan."
+ text_no_configuration_data: "Peranan, jenis, status pakej kerja dan aliran kerja belum dikonfigurasikan lagi. Sangat disarankan untuk memuatkan konfigurasi default. Anda akan dapat mengubahnya setelah ianya dimuatkan."
text_no_notes: "Tiada komen yang tersedia untuk pakej kerja ini."
text_notice_too_many_values_are_inperformant: "Perhatian: Memaparkan lebih daripada 100 item setiap halaman akan meningkatkan masa muat halaman."
text_notice_security_badge_displayed_html: >
@@ -3168,14 +3194,14 @@ ms:
text_warn_on_leaving_unsaved: "Pakej kerja tersebut mengandungi teks yang belum disimpan yang akan hilang jika anda tinggalkan halaman ini."
text_what_did_you_change_click_to_add_comment: "Apakah yang telah anda ubah? Klik untuk tambah komen"
text_wiki_destroy_confirmation: "Adakah anda pasti anda ingin memadam wiki ini dan semua kandungannya?"
- text_wiki_page_destroy_children: "Padam halaman anak dan semua keturunannya"
- text_wiki_page_destroy_question: "Halaman ini mempunyai %{descendants} halaman anak dan keturunannya. Apakah yang anda ingin lakukan?"
- text_wiki_page_nullify_children: "Kekalkan halaman anak sebagai halaman berhubung"
+ text_wiki_page_destroy_children: "Padam halaman anak dan semua turunannya"
+ text_wiki_page_destroy_question: "Halaman ini mempunyai %{descendants} halaman anak dan turunannya. Apakah yang anda ingin lakukan?"
+ text_wiki_page_nullify_children: "Kekalkan halaman anak sebagai halaman asas"
text_wiki_page_reassign_children: "Tetapkan semula halaman anak kepada halaman induk ini"
text_workflow_edit: "Pilih satu peranan dan satu jenis untuk edit aliran kerja tersebut"
text_zoom_in: "Zum masuk"
text_zoom_out: "Zum keluar"
- text_setup_mail_configuration: "Konfigurasi pembekal e-mel anda"
+ text_setup_mail_configuration: "Konfigurasi penyedia e-mel anda"
help_texts:
views:
project: >
@@ -3225,10 +3251,10 @@ ms:
active: "aktif"
activate: "Aktifkan"
activate_and_reset_failed_logins: "Aktifkan dan set semula log masuk yang gagal"
- authentication_provider: "Pemberi Pengesahan"
- identity_url_text: "Pengenal unik dalaman diberikan oleh pemberi pengesahan."
+ authentication_provider: "Penyedia Pengesahan"
+ identity_url_text: "Pengenal unik dalaman disediakan oleh pemberi pengesahan."
authentication_settings_disabled_due_to_external_authentication: >
- Pengguna ini mengesahkan melalui pembekal pengesahan luaran, jadi tiada kata laluan dalam OpenProject untuk diubah.
+ Pengguna ini mengesahkan melalui penyedia pengesahan luaran, jadi tiada kata laluan dalam OpenProject untuk diubah.
authorization_rejected: "Anda tidak dibenarkan untuk daftar masuk."
assign_random_password: "Tetapkan kata laluan rawak (dihantar ke pengguna melalui e-mel)"
blocked: "dikunci sementara"
@@ -3244,24 +3270,24 @@ ms:
no_login: "Pengguna ini mengesahkan melalui log masuk dengan kata laluan. Kerana ia tidak dibenarkan, mereka tidak dapat log masuk."
password_change_unsupported: Penukaran kata laluan tidak disokong.
registered: "berdaftar"
- reset_failed_logins: "Set semula log masuk yang gagal"
+ reset_failed_logins: "Tetapkan semula log masuk yang gagal"
status_user_and_brute_force: "%{user} dan %{brute_force}"
status_change: "Perubahan status"
- text_change_disabled_for_provider_login: "Nama tersebut ditetapkan oleh pembekal log masuk anda dan oleh itu tidak boleh diubah."
+ text_change_disabled_for_provider_login: "Nama tersebut ditetapkan oleh penyedia log masuk anda dan oleh itu tidak boleh diubah."
text_change_disabled_for_ldap_login: "Nama dan e-mel ditetapkan oleh LDAP dan oleh itu tidak boleh diubah."
unlock: "Buka kunci"
- unlock_and_reset_failed_logins: "Buka kunci dan set semula log masuk yang gagal"
+ unlock_and_reset_failed_logins: "Buka kunci dan tetapkan semula log masuk yang gagal"
version_status_closed: "ditutup"
version_status_locked: "dikunci"
- version_status_open: "dibuka"
+ version_status_open: "buka"
note: Perhatian
note_password_login_disabled: "Kata laluan log masuk telah dibatalkan oleh %{configuration}."
warning: Amaran
warning_attachments_not_saved: "%{count} fail tidak dapat disimpan."
warning_imminent_user_limit: >
- Anda menjemput pengguna lebih dari yang disokong pelan semasa anda. Pengguna yang dijemput mungkin tidak dapat sertai persekitaran OpenProject anda. Sila naik taraf pelan anda atau sekat pengguna sedia ada untuk membenarkan pengguna yang dijemput dan berdaftar untuk sertai.
+ Anda menjemput pengguna lebih dari yang disokong pelan semasa anda. Pengguna yang dijemput mungkin tidak dapat sertai persekitaran OpenProject anda. Sila naik taraf pelan anda atau sekat pengguna sedia ada untuk membenarkan pengguna yang dijemput dan berdaftar untuk menyertai.
warning_registration_token_expired: |
- Pengaktifan e-mel telah tamat tempoh. Kami hantar anda yang baharu ke %{email}.
+ Pengaktifan e-mel telah tamat tempoh. Kami telah hantar yang baharu kepada anda di %{email}.
Sila klik pautan di dalamnya untuk mengaktifkan akaun anda.
warning_user_limit_reached: >
Menambah pengguna tambahan akan melebihi had semasa. Sila hubungi pentadbir untuk meningkatkan had pengguna bagi memastikan pengguna luaran dapat mengakses contoh ini.
@@ -3283,10 +3309,10 @@ ms:
menu_item: "Item menu"
menu_item_setting: "Keterlihatan"
wiki_menu_item_for: 'Item menu untuk halaman wiki "%{title}"'
- wiki_menu_item_setting: "Penglihatan"
+ wiki_menu_item_setting: "Keterlihatan"
wiki_menu_item_new_main_item_explanation: >
- Anda sedang memadam item menu utama wiki yang tunggal. Anda kini perlu memilih halaman wiki di mana item menu baharu akan dijanakan. Untuk memadamkan modul wiki tersebut, ianya boleh dinyahaktifkan oleh pentadbir projek.
- wiki_menu_item_delete_not_permitted: Item menu wiki bagi halaman wiki tunggal tidak boleh dipadam.
+ Anda sedang memadam satu-satunya item menu utama wiki. Anda kini perlu memilih halaman wiki di mana item menu baharu akan dijanakan. Untuk memadamkan modul wiki tersebut, ianya boleh dinyahaktifkan oleh pentadbir projek.
+ wiki_menu_item_delete_not_permitted: Item menu wiki bagi satu-satunya halaman wiki tidak boleh dipadam.
#TODO: merge with work_packages top level key
work_package:
updated_automatically_by_child_changes: |
@@ -3297,9 +3323,9 @@ ms:
progress:
label_note: "Perhatian:"
modal:
- work_based_help_text: "% Lengkap secara automatik diperolehi daripada Kerja dan Kerja yang berbaki."
- status_based_help_text: "% Lengkap ditetapkan oleh status pakej kerja."
- migration_warning_text: "Dalam mod pengiraan perkembangan berdasarkan kerja, % Lengkap tidak boleh ditetapkan secara manual dan ianya terikat dengan Kerja. Nilai sedia ada tersebut telah disimpan tetapi tidak boleh diedit. Sila input Kerja dahulu."
+ work_based_help_text: "% Selesai secara automatik diperolehi daripada Kerja dan Kerja yang berbaki."
+ status_based_help_text: "% Selesai ditetapkan oleh status pakej kerja."
+ migration_warning_text: "Dalam mod pengiraan perkembangan berdasarkan kerja, % Selesai tidak boleh ditetapkan secara manual dan ianya terikat kepada Kerja. Nilai sedia ada tersebut telah disimpan tetapi tidak boleh diedit. Sila input Kerja dahulu."
sharing:
count:
zero: "0 pengguna"
@@ -3317,7 +3343,7 @@ ms:
label_toggle_all: "Tukar semua perkongsian"
permissions:
comment: "Komen"
- comment_description: "Boleh lihat dan komen tentang pakej kerja ini."
+ comment_description: "Boleh lihat dan komen berkenaan pakej kerja ini."
denied: "Anda tidak mempunyai kebenaran untuk berkongsi pakej kerja."
edit: "Edit"
edit_description: "Boleh lihat, komen dan edit pakej kerja ini."
@@ -3330,7 +3356,7 @@ ms:
text_empty_state_description: "Pakej kerja masih belum dikongsikan dengan sesiapa lagi."
text_empty_state_header: "Tidak dikongsikan"
text_user_limit_reached: "Menambah pengguna tambahan akan melebihi had semasa. Sila hubungi pentadbir untuk meningkatkan had pengguna bagi memastikan pengguna luaran dapat mengakses pakej kerja ini."
- text_user_limit_reached_admins: 'Menambah pengguna tambahan akan melebihi had semasa. Sila naik taraf pelan anda untuk dapat menambah lebih banyak pengguna.'
+ text_user_limit_reached_admins: 'Menambah pengguna tambahan akan melebihi had semasa. Sila naik taraf pelan anda untuk membolehkan untuk menambah lebih banyak pengguna.'
warning_user_limit_reached: >
Menambah pengguna tambahan akan melebihi had semasa. Sila hubungi pentadbir untuk meningkatkan had pengguna bagi memastikan pengguna luaran dapat mengakses pakej kerja ini.
warning_user_limit_reached_admin: >
@@ -3350,12 +3376,12 @@ ms:
additional_privileges_project_or_group: "Mungkin mempunyai keistimewaan tambahan (sebagai ahli projek atau kumpulan)"
working_days:
info: >
- Hari yang tidak dipilih akan dilangkau semasa penjadualan pakej kerja (dan tidak disertakan dalam jumlah hari). Ini boleh digantikan pada peringkat pakej kerja.
+ Hari yang tidak dipilih akan dilangkau semasa penjadualan pakej kerja (dan tidak termasuk dalam kiraan hari). Ini boleh digantikan di peringkat pakej-kerja.
instance_wide_info: >
- Tarikh yang ditambah ke senarai dibawah diterima sebagai tidak berfungsi dan dilangkau semasa menjadualkan pakej kerja.
+ Tarikh yang ditambah ke senarai dibawah diterima sebagai tidak berfungsi dan dilangkau semasa penjadualan pakej kerja.
change_button: "Tukar hari bekerja"
warning: >
- Menukar hari mana dalam seminggu dianggap hari bekerja atau hari tidak bekerja boleh memberi kesan kepada hari mula dan tamat bagi semua pakej kerja dalam semua projek dalam kejadian ini. Sila ambil perhatian bahawa perubahan hanya dilaksanakan selepas anda klik butang terapkan perubahan.
+ Penukaran hari dalam seminggu yang dianggap sebagai hari bekerja atau hari tidak bekerja akan mempengaruhi hari mula dan akhir semua pakej kerja dalam semua projek bagi contoh ini.
journal_note:
changed: _**Hari bekerja** telah diubah (%{changes})._
days:
@@ -3392,13 +3418,13 @@ ms:
invalid_relation: "Hubungan tersebut adalah tidak sah."
invalid_resource: "Untuk ciri-ciri '%{property}' sebuah pautan seperti '%{expected}' dijangkakan, tetapi mendapat '%{actual}'."
invalid_signal:
- embed: "Permintaan menyemat %{invalid} tidak disokong. Penyematan yang disokong adalah %{supported}."
+ embed: "Permintaan menyemat %{invalid} tidak disokong. Penyematan yang disokong ialah %{supported}."
select: "Permintaan %{invalid} yang dipilih tidak disokong. Pilihan yang disokong ialah %{supported}."
invalid_user_status_transition: "Status akaun pengguna semasa tidak membenarkan operasi ini."
missing_content_type: "tidak ditentukan"
missing_property: "Ciri-ciri yang hilang '%{property}'."
missing_request_body: "Tiada badan permintaan."
- missing_or_malformed_parameter: "Parameter pertanyaan '%{parameter}' tidak ditemui atau cacat."
+ missing_or_malformed_parameter: "Parameter pertanyaan '%{parameter}' tidak ditemui atau tidak betul."
multipart_body_error: "Badan permintaan tidak mempunyai bahagian multipart seperti yang dijangka."
multiple_errors: "Beberapa kekangan ruang telah dilanggar."
unable_to_create_attachment: "Lampiran tidak boleh dicipta"
@@ -3422,31 +3448,31 @@ ms:
doorkeeper:
pre_authorization:
status: "Pra-kebenaran"
- auth_url: "Auth URL"
+ auth_url: "URL Auth"
access_token_url: "Akses token URL"
errors:
messages:
#Common error messages
invalid_request:
- unknown: "Permintaan tersebut tidak mengandungi parameter yang diperlukan, termasuk nilai parameter yang tidak disokong, atau sebaliknya telah cacat."
+ unknown: "Permintaan tersebut tidak mengandungi parameter yang diperlukan, termasuk nilai parameter yang tidak disokong, atau sebaliknya tidak betul."
missing_param: "Parameter yang diperlukan hilang: %{value}."
request_not_authorized: "Permintaan perlu dibenarkan. Parameter yang diperlukan untuk membenarkan permintaan tiada atau tidak sah."
invalid_redirect_uri: "Pengubah hala URI yang diminta tidak betul atau tidak sepadan dengan pengubah hala URI pelanggan."
unauthorized_client: "Pelanggan tersebut tidak dibenarkan untuk melaksanakan permintaan ini menggunakan kaedah ini."
access_denied: "Pemilik sumber atau server kebenaran menafikan permintaan ini."
- invalid_scope: "Skop yang diminta adalah tidak sah, tidak diketahui, atau salah bentuk."
+ invalid_scope: "Skop yang diminta adalah tidak sah, tidak diketahui, atau tidak betul."
invalid_code_challenge_method: "Kaedah kod cabaran mesti biasa atau S256."
server_error: "Server kebenaran mengalami keadaan yang tidak dijangka yang menghalangnya daripada memenuhi permintaan."
temporarily_unavailable: "Server kebenaran pada masa ini tidak dapat mengendalikan permintaan kerana beban berlebihan sementara atau penyelenggaraan server."
#Configuration error messages
credential_flow_not_configured: "Aliran Kelayakan Kata Laluan Pemilik Sumber telah gagal disebabkan oleh Doorkeeper.configure.resource_owner_authenticator tidak dikonfigurasikan."
resource_owner_authenticator_not_configured: "Carian Pemilik Sumber gagal kerana Doorkeeper.configure.resource_owner_authenticator tidak dikonfigurasikan."
- admin_authenticator_not_configured: "Akses ke panel admin dilarang kerana Doorkeeper.configure.admin_authenticator tidak dikonfigurasi."
+ admin_authenticator_not_configured: "Akses ke panel pentadbir dilarang kerana Doorkeeper.configure.admin_authenticator tidak dikonfigurasi."
#Access grant errors
unsupported_response_type: "Server kebenaran tidak menyokong jenis tindak balas ini."
unsupported_response_mode: "Server kebenaran tidak menyokong mod tindak balas ini."
#Access token errors
- invalid_client: "Pengesahan pelanggan gagal kerana pelanggan yang tidak diketahui, tiada pengesahan pelanggan yang disertakan, atau kaedah pengesahan yang tidak disokong."
+ invalid_client: "Pengesahan pelanggan gagal kerana pelanggan yang tidak diketahui, tiada pengesahan pelanggan yang disertakan, atau kaedah pengesahan tidak disokong."
invalid_grant: "Pemberian kebenaran yang diberikan adalah tidak sah, luput, dibatalkan, tidak sepadan dengan pengubah hala URI yang digunakan dalam permintaan kebenaran, atau dikeluarkan kepada pelanggan lain."
unsupported_grant_type: "Jenis pemberian kebenaran tidak disokong oleh server pengesahan."
invalid_token:
@@ -3472,9 +3498,9 @@ ms:
instructions:
name: "Nama aplikasi anda. Ini akan dipaparkan ke pengguna lain selepas kebenaran."
redirect_uri_html: >
- URL yang dibenarkan membenarkan pengguna boleh diubah hala. Satu entri setiap baris. Jika anda mendaftar aplikasi desktop, guna URL berikut.
- confidential: "Semak jika aplikasi akan digunakan dimana rahsia pelanggan boleh dikekalkan sulit. Mobile apps asal dan Single Page Apps dianggap sebagai tidak sulit."
- scopes: "Tandakan skop yang anda mahu aplikasi untuk berikan akses. Jika tiada skop ditandakan, api_v3 akan diandaikan."
+ URL yang dibenarkan membenarkan pengguna boleh diubah hala. Satu entri setiap baris. Jika anda mendaftar aplikasi desktop, gunakan URL berikut.
+ confidential: "Semak jika aplikasi akan digunakan dimana rahsia pelanggan boleh dikekalkan sulit. Aplikasi mudah alih asal dan Single Page Apps dianggap sebagai tidak sulit."
+ scopes: "Tandakan skop yang anda mahu untuk berikan akses ke aplikasi tersebut. Jika tiada skop ditandakan, api_v3 akan diandaikan."
client_credential_user_id: "ID pengguna pilihan untuk menyamar apabila pelanggan menggunakan aplikasi ini. Tinggalkan kosong untuk benarkan akses awam sahaja."
register_intro: "Jika anda sedang membangunkan aplikasi pelanggan API OAuth untuk OpenProject, anda boleh mendaftarkannya menggunakan borang ini untuk semua pengguna menggunakannya."
default_scopes: ""
@@ -3507,7 +3533,7 @@ ms:
client_credentials_impersonation_html: >
Secara default, OpenProject menyediakan kebenaran OAuth 2.0 melalui %{authorization_code_flow_link}. Anda boleh memilih untuk mengaktifkan %{client_credentials_flow_link}, tetapi anda mesti menyediakan pengguna yang akan mewakili permintaan.
authorization_error: "Sebuah ralat kebenaran telah berlaku."
- revoke_my_application_confirmation: "Adakah anda benar-benar mahu keluarkan aplikasi ini? Ini akan menarik balik %{token_count} aktif darinya."
+ revoke_my_application_confirmation: "Adakah anda benar-benar mahu memadam aplikasi ini? Ini akan menarik balik %{token_count} yang aktif darinya."
my_registered_applications: "Aplikasi OAuth berdaftar"
oauth_client:
urn_connection_status:
@@ -3517,11 +3543,11 @@ ms:
labels:
label_oauth_integration: "Integrasi OAuth2"
label_redirect_uri: "Ubah hala URI"
- label_request_token: "Permintaan token"
+ label_request_token: "Token permintaan"
label_refresh_token: "Token muat semula"
errors:
oauth_authorization_code_grant_had_errors: "Pemberian pengesahan OAuth2 tidak berjaya"
- oauth_reported: "Pembekal OAuth2 melaporkan"
+ oauth_reported: "Penyedia OAuth2 melaporkan"
oauth_returned_error: "OAuth2 telah kembalikan sebuah ralat"
oauth_returned_json_error: "OAuth2 telah kembalikan ralat JSON"
oauth_returned_http_error: "OAuth2 telah kembalikan ralat rangkaian"
@@ -3533,13 +3559,13 @@ ms:
Ralat dalaman: Memanggil refresh_token tanpa token yang sedia ada sebelum ini.
refresh_token_updated_failed: "Ralat semasa kemas kini OAuthClientToken"
oauth_client_not_found_explanation: >
- Ralat muncul selepas anda mengemas kini client_id dan client_secret di Openproject, tetapi belum mengemas kini ruangan 'URI Kembali' dalam pembekal OAuth2.
+ Ralat muncul selepas anda mengemas kini client_id dan client_secret di Openproject, tetapi belum mengemas kini ruangan 'URI Kembali' dalam penyedia OAuth2.
oauth_code_not_present: "'Kod' OAuth2 tidak ditemui dalam titik terakhir 'panggilan balik' (redirect_url)."
oauth_code_not_present_explanation: >
Ralat ini muncul jika anda telah memilih response_type yang salah dalam pembekal OAuth2. Response_type perlu 'kod' atau serupa.
oauth_state_not_present: "'Kondisi' OAuth2 tidak ditemui dalam titik terakhir 'panggilan balik' (ubah hala_url)."
oauth_state_not_present_explanation: >
- 'Kondisi' digunakan untuk menunjukkan ke OpenProject tempat untuk meneruskan selepas kebenaran OAuth2 berjaya. Ketiadaan 'Kondisi' adalah ralat dalaman yang mungkin muncul semasa penyediaan. Sila hubungi pentadbir sistem anda.
+ 'Kondisi' digunakan untuk menunjukkan ke OpenProject tempat untuk meneruskan selepas kebenaran OAuth2 berjaya. Ketiadaan 'kondisi' adalah ralat dalaman yang mungkin muncul semasa penyediaan. Sila hubungi pentadbir sistem anda.
rack_oauth2:
client_secret_invalid: "Rahsia pelanggan adalah tidak sah (rahsia_pelanggan_tidak sah)"
invalid_request: >
@@ -3553,7 +3579,7 @@ ms:
http:
request:
failed_authorization: "Permintaan dari pihak server gagal mengesahkan dirinya sendiri."
- missing_authorization: "Permintaan dari pihak server gagal disebabkan maklumat pengesahan yang hilang."
+ missing_authorization: "Permintaan dari pihak server gagal disebabkan maklumat pengesahan yang hilang."
response:
unexpected: "Tindak balas yang tidak dijangka diterima."
you: anda
diff --git a/config/locales/crowdin/ne.yml b/config/locales/crowdin/ne.yml
index 4141e569a1b3..135c98c3403c 100644
--- a/config/locales/crowdin/ne.yml
+++ b/config/locales/crowdin/ne.yml
@@ -300,6 +300,12 @@ ne:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: There are currently no types available.
form:
@@ -448,12 +454,20 @@ ne:
स्थितिको अपवाद बिना कुनै पनि विशेषताहरू परिवर्तन गर्न सकिँदैन।
द्रष्टव्य: प्रारम्भिक मानहरू (जस्तै, from children or relations) लागू हुनेछ।
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: There are currently no work package statuses.
no_results_content_text: Add a new status
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -623,6 +637,7 @@ ne:
status:
is_closed: "Work package closed"
is_readonly: "कार्य प्याकेज पढ्ने-मात्र"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "द्रष्टव्यहरु"
member:
@@ -959,6 +974,14 @@ ne:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1143,18 +1166,6 @@ ne:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Changesets"
message: "Forums"
@@ -1605,6 +1616,12 @@ ne:
pdf_gantt: "PDF Gantt"
image:
omitted: "छवि निर्यात गरिएको छैन।"
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1658,7 +1675,7 @@ ne:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1675,8 +1692,9 @@ ne:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2333,7 +2351,7 @@ ne:
label_workflow: "Workflow"
label_workflow_plural: "Workflows"
label_workflow_summary: "Summary"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 closed"
other: "%{count} closed"
@@ -2933,6 +2951,9 @@ ne:
setting_cross_project_work_package_relations: "Allow cross-project work package relations"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "Date"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Default language"
setting_default_projects_modules: "Default enabled modules for new projects"
setting_default_projects_public: "New projects are public by default"
@@ -2948,6 +2969,12 @@ ne:
setting_feeds_limit: "Feed content limit"
setting_file_max_size_displayed: "Max size of text files displayed inline"
setting_host_name: "Host name"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3389,12 +3416,12 @@ ne:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/nl.yml b/config/locales/crowdin/nl.yml
index 26461eab2cc9..3e7ca5fe74d8 100644
--- a/config/locales/crowdin/nl.yml
+++ b/config/locales/crowdin/nl.yml
@@ -297,6 +297,12 @@ nl:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Er zijn momenteel geen types beschikbaar.
form:
@@ -445,12 +451,20 @@ nl:
geen kenmerken kunnen worden gewijzigd met uitzondering van de status.
Opmerking: overgenomen waarden (bijvoorbeeld van kinderen of betrekkingen) blijft van toepassing.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Klik op toewijzen of wijzigen van de kleur van deze status.
het wordt weergegeven in de statusknop en kan worden gebruikt voor het benadrukken van de werkpakketten in de tabel.
index:
no_results_title_text: Er zijn momenteel geen werkpakket statussen.
no_results_content_text: Voeg een nieuwe status toe
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Licht"
light_high_contrast: "Licht hoog contrast"
@@ -620,6 +634,7 @@ nl:
status:
is_closed: "Werkpakket gesloten"
is_readonly: "Werkpakket is alleen-lezen"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Notities"
member:
@@ -956,6 +971,14 @@ nl:
base:
working_days_are_missing: "Ten minste één dag van de week moet worden gedefinieerd als een werkdag."
previous_working_day_changes_unprocessed: "De vorige wijzigingen in de configuratie van de werkdagen zijn nog niet toegepast."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1140,18 +1163,6 @@ nl:
other: "%{count} uur"
updated: "veranderd van %{old_value} naar %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "veranderd van %{old_value} naar %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "veranderd van %{old_value} naar %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Wijzigingensets"
message: "Fora"
@@ -1602,6 +1613,12 @@ nl:
pdf_gantt: "PDF Gantt"
image:
omitted: "Afbeelding niet geëxporteerd."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: u
days: d
@@ -1655,7 +1672,7 @@ nl:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1672,8 +1689,9 @@ nl:
working: "%{date} werkt nu"
non_working: "%{date} is nu niet actief"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2330,7 +2348,7 @@ nl:
label_workflow: "Werkstroom"
label_workflow_plural: "Workflows"
label_workflow_summary: "Samenvatting"
- label_working_days: "Werkdagen"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 gesloten"
other: "%{count} gesloten"
@@ -2929,6 +2947,9 @@ nl:
setting_cross_project_work_package_relations: "Sta werkpakketten over meerdere projecten toe"
setting_first_week_of_year: "De eerste week in het jaar bevat"
setting_date_format: "Datum"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Standaard taal"
setting_default_projects_modules: "Standaard actieve modules voor nieuwe projecten"
setting_default_projects_public: "Nieuwe projecten zijn standaard publiek"
@@ -2944,6 +2965,12 @@ nl:
setting_feeds_limit: "Feed inhoud limiet"
setting_file_max_size_displayed: "Maximale grootte van tekstbestanden inline weergegeven"
setting_host_name: "Hostnaam"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activatie e-mail verloopt na"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3384,12 +3411,12 @@ nl:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Wijzig werkdagen"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Werkdagen** veranderd (%{changes})._
days:
diff --git a/config/locales/crowdin/no.yml b/config/locales/crowdin/no.yml
index e49c5dcfc824..954c37419e75 100644
--- a/config/locales/crowdin/no.yml
+++ b/config/locales/crowdin/no.yml
@@ -266,7 +266,7 @@
my: "Mine prosjekter"
favored: "Favorittprosjekter"
archived: "Arkiverte prosjekter"
- public: "Public project lists"
+ public: "Offentlige prosjektlister"
my_private: "Mine private prosjektlister"
new:
placeholder: "Ny prosjektliste"
@@ -294,12 +294,18 @@
actions:
label_enable_single: "Aktivert i dette prosjektet, klikk for å deaktivere"
label_disable_single: "Deaktivert i dette prosjektet, klikk for å aktivere"
- deactivate_for_project: "Deactivate for this project"
+ deactivate_for_project: "Deaktiver for dette prosjektet"
label_enable_all: "Aktiver alle"
label_disable_all: "Deaktiver alle"
is_required_blank_slate:
- heading: Required in all projects
- description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ heading: Påkrevd i alle prosjekter
+ description: Prosjektattributten er aktivert i alle prosjekter fordi "Påkrevd i alle prosjekter"-alternativet er valgt. Attributten kan ikke deaktiveres for hvert enkelt prosjekt.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Det finnes ingen tilgjengelige typer.
form:
@@ -317,11 +323,11 @@
success: "Den endrede listen er lagret"
failure: "Den endrede listen kan ikke lagres: %{errors}"
publish:
- success: "The list has been made public"
- failure: "The list cannot be made public: %{errors}"
+ success: "Listen er blitt offentliggjort"
+ failure: "Listen kan ikke offentliggjøres: %{errors}"
unpublish:
- success: "The list has been made private"
- failure: "The list cannot be made private: %{errors}"
+ success: "Listen er blitt gjort privat"
+ failure: "Listen kan ikke gjøres privat: %{errors}"
can_be_saved: "Listen endret:"
can_be_saved_as: "Endringene kan bare lagres i en ny liste."
members:
@@ -448,12 +454,19 @@
Ingen attributter kan endres med unntak av status.
Merknad: Arvede verdier (for eksempel fra barn eller relasjoner) vil fortsatt gjelde.
+ status_excluded_from_totals_text: |-
+ Velg denne innstillingen for å utelukke arbeidspakker med denne statusen fra oppsummeringer for Arbeid, Gjenstående arbeid og % Ferdig i et hierarki.
status_color_text: |
Klikk for å tilknytte eller endre fargen på denne statusen.
Den vises i statusknappen og kan brukes til å fremheve arbeidspakker i tabellen.
index:
no_results_title_text: Det er for tiden ingen status for arbeidspakken.
no_results_content_text: Legg til en ny status
+ headers:
+ is_default: "Standard"
+ is_closed: "Lukket"
+ is_readonly: "Kun lesetilgang"
+ excluded_from_totals: "Unntatt fra totaler"
themes:
light: "Lyst"
light_high_contrast: "Lys høy kontrast"
@@ -623,6 +636,7 @@
status:
is_closed: "Arbeidspakke lukket"
is_readonly: "Arbeidspakken er skrivebeskyttet"
+ excluded_from_totals: "Unnta fra beregning av totaler i hierarki"
journal:
notes: "Notater"
member:
@@ -763,7 +777,7 @@
before_or_equal_to: "må være før eller lik %{date}."
blank: "kan ikke være blank."
blank_nested: "må ha egenskapen '%{property}' aktivert."
- cannot_delete_mapping: "is required. Cannot be deleted."
+ cannot_delete_mapping: "er påkrevd. Kan ikke slettes."
cant_link_a_work_package_with_a_descendant: "En arbeidspakke kan ikke knyttes til en av sine deloppgaver."
circular_dependency: "En slik relasjon ville lage en sirkulær avhengighet."
confirmation: "samsvarer ikke med %{attribute}."
@@ -924,8 +938,8 @@
nonexistent: "Kolonnen '%{column}' eksisterer ikke."
format: "%{message}"
group_by_hierarchies_exclusive: "er gjensidig eksklusiv med grupper med '%{group_by}'. Du kan ikke aktivere begge."
- can_only_be_modified_by_owner: "The query can only be modified by its owner."
- need_permission_to_modify_public_query: "You cannot modify a public query."
+ can_only_be_modified_by_owner: "Spørringen kan bare endres av sin eier."
+ need_permission_to_modify_public_query: "Du kan ikke endre på et offentlig søk."
filters:
custom_fields:
inexistent: "Det er ikke noe egendefinert felt for filteret."
@@ -959,6 +973,14 @@
base:
working_days_are_missing: "Minst en ukedag må defineres som en virkedag."
previous_working_day_changes_unprocessed: "De tidligere endringene i konfigurasjonen av arbeidsdager har ikke blitt brukt ennå."
+ hours_per_day_are_missing: "Antall timer per dag må defineres."
+ days_per_week_are_missing: "Antall dager per uke må være definert."
+ days_per_month_are_missing: "Antall dager per måned må defineres."
+ durations_are_not_positive_numbers: "Varigheten må være positive tall."
+ hours_per_day_is_out_of_bounds: "Timer per dag kan ikke være mer enn 24"
+ days_per_week_is_out_of_bounds: "Dager per uke kan ikke være mer enn 7"
+ days_per_month_is_out_of_bounds: "Dager per måned kan ikke være mer enn 31"
+ days_per_week_and_days_per_month_are_inconsistent: "Antall dager per uke og antall dager per måned må være konsekvent."
time_entry:
attributes:
hours:
@@ -1143,18 +1165,6 @@
other: "%{count} timer"
updated: "endret fra %{old_value} til %{value}"
logged_for: "Logget for"
- meeting_agenda_item:
- duration:
- added: "satt til %{value}"
- added_html: "satt til %{value}"
- removed: "fjernet"
- updated: "endret fra %{old_value} til %{value}"
- updated_html: "endret fra %{old_value} til %{value}"
- position:
- updated: "omsortert"
- work_package:
- updated: "endret fra %{old_value} til %{value}"
- updated_html: "endret fra %{old_value} til %{value}"
filter:
changeset: "Changesets"
message: "Forum"
@@ -1333,8 +1343,8 @@
button_revoke_access: "Fjern tilgang"
button_revoke_all: "Fjern alle"
button_revoke_only: "Fjern kun %{shared_role_name}"
- button_publish: "Make public"
- button_unpublish: "Make private"
+ button_publish: "Offentliggjør"
+ button_unpublish: "Gjør privat"
consent:
checkbox_label: Jeg har merket meg og samtykker til det ovenfor.
failure_message: Samtykke mislyktes, kan ikke fortsette.
@@ -1605,6 +1615,12 @@
pdf_gantt: "PDF Gantt"
image:
omitted: "Bilde ikke eksportert."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: t
days: d
@@ -1658,7 +1674,7 @@
dates_changed: "Datoer endret"
default_attribute_written: "Skrivebeskyttet attributter skrevet"
progress_mode_changed_to_status_based: "Fremdriftsberegning oppdatert"
- status_p_complete_changed: "Status % ferdig endret"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system oppdatering:"
cause_descriptions:
work_package_predecessor_changed_times: etter endringer i forgjenger %{link}
@@ -1675,8 +1691,9 @@
working: "%{date} er nå arbeidsdag"
non_working: "%{date} er nå arbeidsfri"
progress_mode_changed_to_status_based: Framdriftsmodus satt til statusbasert
- status_p_complete_changed: >-
- % ferdigstilt verdi for status '%{status_name}' endret fra %{old_value}% til %{new_value}%
+ status_excluded_from_totals_set_to_false_message: nå inkludert i hierarkiske summer
+ status_excluded_from_totals_set_to_true_message: nå ekskludert fra hierarkiske summer
+ status_percent_complete_changed: "% ferdig endret fra %{old_value}% til %{new_value}%"
system_update:
file_links_journal: >
Fra nå av vil aktivitet knyttet til linker (filer lagret i eksterne lagringer) vises her i aktivitetsfanen. Følgende representerer aktivitet med lenker som allerede eksisterer:
@@ -2333,7 +2350,7 @@
label_workflow: "Arbeidsflyt"
label_workflow_plural: "Arbeidsflyt"
label_workflow_summary: "Sammendrag"
- label_working_days: "Arbeidsdager"
+ label_working_days_and_hours: "Arbeidsdager og timer"
label_x_closed_work_packages_abbr:
one: "1 lukket"
other: "%{count} stengt"
@@ -2717,7 +2734,7 @@
permission_save_bcf_queries: "Lagre BCF-spørringer"
permission_manage_public_bcf_queries: "Administrere offentlige BCF-spørringer"
permission_edit_attribute_help_texts: "Rediger hjelpetekster for egenskap"
- permission_manage_public_project_queries: "Manage public project lists"
+ permission_manage_public_project_queries: "Administrere offentlige prosjektlister"
placeholders:
default: "-"
project:
@@ -2933,6 +2950,9 @@
setting_cross_project_work_package_relations: "Tillat relasjoner mellom arbeidspakker i ulike prosjekter"
setting_first_week_of_year: "Første uke i år inneholder"
setting_date_format: "Dato"
+ setting_days_per_month: "Dager per måned"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Standardspråk"
setting_default_projects_modules: "Standardaktiverte moduler for nye prosjekter"
setting_default_projects_public: "Nye prosjekter er offentlige som standard"
@@ -2948,6 +2968,12 @@
setting_feeds_limit: "Innholdsgrense for Feed"
setting_file_max_size_displayed: "Maks størrelse på tekstfiler som vises inline"
setting_host_name: "Vertsnavn"
+ setting_hours_per_day: "Timer per dag"
+ setting_hours_per_day_explanation: >-
+ Dette vil definere hva som anses som en "dag" når varigheten vises på en mer naturlig måte (for eksempel hvis dagen er 8 timer, vil 32 timer være 4 dager).
+ setting_days_per_week: "Dager per uke"
+ setting_days_per_week_explanation: >-
+ Denne vil definere hva som regnes som en "uke" når varigheten vises på en mer naturlig måte (for eksempel hvis en uke er på 5 dager, er 15 dager 3 uker).
setting_invitation_expiration_days: "Aktiverings e-post utløper etter"
setting_work_package_done_ratio: "Beregning av fremdrift"
setting_work_package_done_ratio_field: "Arbeidsbasert"
@@ -3389,12 +3415,12 @@
additional_privileges_project_or_group: "Kan ha flere privilegier (som prosjekt- eller gruppemedlem)"
working_days:
info: >
- Hoppet over dager som ikke er valgt, ved planlegging av arbeidspakker (og ikke inkludert i antall dager). Disse kan overstyres på et arbeidspakkenivå.
+ Hoppet over dager som ikke er valgt ved planlegging av arbeidspakker (og ikke inkludert i antall dager). Disse kan overstyres på arbeidspakkenivå.
instance_wide_info: >
Datoer som er lagt til i listen nedenfor regnes som arbeidsfrie og hoppet over når arbeidspakker planlegges.
change_button: "Endre arbeidsdager"
warning: >
- Endring av hvilke ukedager som regnes som arbeidsdager eller arbeidsfrie dager kan påvirke start- og sluttdager for alle arbeidspakker i alle prosjekter i denne forekomsten. Vær oppmerksom på at endringer kun brukes etter at du har klikket på knappen Bruk endringer.
+ Endring av hvilke ukedager som regnes som arbeidsdager eller arbeidsfrie dager kan påvirke start- og sluttdager for alle arbeidspakker i alle prosjekter i denne forekomsten.
journal_note:
changed: _**Arbeidsdager** endret (%{changes})._
days:
diff --git a/config/locales/crowdin/pl.yml b/config/locales/crowdin/pl.yml
index a51d3a1e5157..407c45647dcc 100644
--- a/config/locales/crowdin/pl.yml
+++ b/config/locales/crowdin/pl.yml
@@ -297,6 +297,12 @@ pl:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Nie ma dostępnych typów.
form:
@@ -457,12 +463,20 @@ pl:
Nie można zmienić żadnych atrybutów z wyjątkiem stanu.
Uwaga: wartości dziedziczone (np. po elementach podrzędnych lub relacjach) będą nadal stosowane.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Kliknij, aby przypisać lub zmienić kolor tego stanu.
Jest on wyświetlany w przycisku stanu i można go używać do wyróżniania pakietów roboczych w tabeli.
index:
no_results_title_text: Nie ma aktualnie żadnych statusów Zestawu zadań.
no_results_content_text: Dodaj nowy status
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Jasny"
light_high_contrast: "Jasny, wysoki kontrast"
@@ -634,6 +648,7 @@ pl:
status:
is_closed: "Zadanie zamknięte"
is_readonly: "Pakiet roboczy tylko do odczytu"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Notatki"
member:
@@ -970,6 +985,14 @@ pl:
base:
working_days_are_missing: "Co najmniej jeden dzień tygodnia musi być zdefiniowany jako dzień roboczy."
previous_working_day_changes_unprocessed: "Poprzednie zmiany konfiguracji dni roboczych nie zostały jeszcze zastosowane."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1170,18 +1193,6 @@ pl:
other: "%{count} godziny"
updated: "zmieniono z %{old_value} na %{value}"
logged_for: "Zalogowano przez"
- meeting_agenda_item:
- duration:
- added: "ustawiono na %{value}"
- added_html: "ustawiono na %{value}"
- removed: "usunięto"
- updated: "zmieniono z %{old_value} na %{value}"
- updated_html: "zmieniono z %{old_value} na %{value}"
- position:
- updated: "zmieniono kolejność"
- work_package:
- updated: "zmieniono z %{old_value} na %{value}"
- updated_html: "zmieniono z %{old_value} na %{value}"
filter:
changeset: "Zestawy zmian"
message: "Fora"
@@ -1668,6 +1679,12 @@ pl:
pdf_gantt: "Wykres Gantta w formacie PDF"
image:
omitted: "Nie wyeksportowano obrazu"
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1721,7 +1738,7 @@ pl:
dates_changed: "Daty zostały zmienione"
default_attribute_written: "Zapisano atrybuty tylko do odczytu"
progress_mode_changed_to_status_based: "Zaktualizowano obliczenie postępu"
- status_p_complete_changed: "Zmieniono status % ukończenia"
+ status_changed: "Status '%{status_name}'"
system_update: "Aktualizacja systemu OpenProjekt:"
cause_descriptions:
work_package_predecessor_changed_times: przez zmiany poprzednika %{link}
@@ -1738,8 +1755,9 @@ pl:
working: "%{date} jest teraz dniem roboczym"
non_working: "%{date} jest teraz wolnym od pracy"
progress_mode_changed_to_status_based: Tryb obliczania postępu ustawiono na oparty na statusie
- status_p_complete_changed: >-
- Wartość % ukończenia dla statusu „%{status_name}” zmieniono z %{old_value}% na %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
Od teraz aktywność związana z linkami do plików (plików przechowywanych w magazynach zewnętrznych) będzie wyświetlana na karcie Aktywność. Poniżej przedstawiono aktywność dotyczącą linków, które już istniały:
@@ -2396,7 +2414,7 @@ pl:
label_workflow: "Przepływ pracy"
label_workflow_plural: "Przepływ zadań"
label_workflow_summary: "Podsumowanie"
- label_working_days: "Dni robocze"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 zamknięty"
other: "Liczba zamkniętych: %{count}"
@@ -2997,6 +3015,9 @@ pl:
setting_cross_project_work_package_relations: "Zezwól na powiązania pakietów roboczych pomiędzy projektami"
setting_first_week_of_year: "Pierwszy tydzień w roku zawiera"
setting_date_format: "Data"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Język domyślny"
setting_default_projects_modules: "Domyślnie włączone moduły dla nowych projektów"
setting_default_projects_public: "Nowe projekty są publiczne (domyślnie)"
@@ -3012,6 +3033,12 @@ pl:
setting_feeds_limit: "Feed content limit"
setting_file_max_size_displayed: "Maksymalny rozmiar plików tekstowych wyświetlanych w treści"
setting_host_name: "Nazwa hosta"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Ważność aktywacyjnej waidomości e-mail wygasa po"
setting_work_package_done_ratio: "Obliczenie postępu"
setting_work_package_done_ratio_field: "Oparte na pracy"
@@ -3455,12 +3482,12 @@ pl:
additional_privileges_project_or_group: "Może mieć dodatkowe uprawnienia (jako członek projektu lub grupy)"
working_days:
info: >
- Dni, które nie zostały wybrane, są pomijane podczas planowania pakietów roboczych (i nie są uwzględnione w liczbie dni). Mogą one zostać zastąpione na poziomie pakietu roboczego.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Daty dodane do poniższej listy są uważane za niedziałające i są pomijane podczas planowania pakietów roboczych.
change_button: "Zmień dni robocze"
warning: >
- Zmiana dni tygodnia, które są uważane za dni robocze lub dni nierobocze może mieć wpływ na dni rozpoczęcia i zakończenia wszystkich pakietów roboczych we wszystkich projektach w tym wystąpieniu. Pamiętaj, że zmiany są stosowane dopiero po kliknięciu przycisku Zastosuj zmiany.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _Zmieniono **Dni robocze** (%{changes})._
days:
diff --git a/config/locales/crowdin/pt-BR.yml b/config/locales/crowdin/pt-BR.yml
index 15b1bf395ee2..ba6299a3d5b5 100644
--- a/config/locales/crowdin/pt-BR.yml
+++ b/config/locales/crowdin/pt-BR.yml
@@ -299,6 +299,12 @@ pt-BR:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Atualmente, não há tipos disponíveis.
form:
@@ -447,12 +453,20 @@ pt-BR:
Nenhum atributo pode ser alterado com exceção da situação.
Nota: valores herdados (por exemplo, de filhos ou relações) ainda serão aplicados.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Clique para atribuir ou alterar a cor desta situação.
É exibido no botão de situação e pode ser usado para destacar pacotes de trabalho na tabela.
index:
no_results_title_text: Atualmente, não há nenhuma situação de pacote de trabalho.
no_results_content_text: Adicionar uma nova situação
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Claro"
light_high_contrast: "Contraste alto claro"
@@ -622,6 +636,7 @@ pt-BR:
status:
is_closed: "Pacote de trabalho fechado"
is_readonly: "Pacote de trabalho somente leitura"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Anotações"
member:
@@ -958,6 +973,14 @@ pt-BR:
base:
working_days_are_missing: "Pelo menos um dia da semana deve ser definido como um dia útil."
previous_working_day_changes_unprocessed: "As alterações anteriores na configuração de dias úteis ainda não foram aplicadas."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1142,18 +1165,6 @@ pt-BR:
other: "%{count} horas"
updated: "alterado de %{old_value} para %{value}"
logged_for: "Registrado por"
- meeting_agenda_item:
- duration:
- added: "definido como %{value}"
- added_html: "definido como %{value}"
- removed: "removido"
- updated: "alterado de %{old_value} para %{value}"
- updated_html: "alterado de %{old_value} para %{value}"
- position:
- updated: "reorganizado"
- work_package:
- updated: "alterado de %{old_value} para %{value}"
- updated_html: "alterado de %{old_value} para %{value}"
filter:
changeset: "Cj de alterações"
message: "Fóruns"
@@ -1604,6 +1615,12 @@ pt-BR:
pdf_gantt: "Gantt em PDF"
image:
omitted: "Imagem não exportada."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1657,7 +1674,7 @@ pt-BR:
dates_changed: "Data modificada"
default_attribute_written: "Atributos de somente leitura escritos"
progress_mode_changed_to_status_based: "Cálculo de progresso atualizado"
- status_p_complete_changed: "Estado da % de conclusão alterado"
+ status_changed: "Status '%{status_name}'"
system_update: "Atualização do sistema OpenProject:"
cause_descriptions:
work_package_predecessor_changed_times: por alterações ao antecessor %{link}
@@ -1674,8 +1691,9 @@ pt-BR:
working: "%{date} agora está funcionando"
non_working: "%{date} não está funcionando agora"
progress_mode_changed_to_status_based: Modo de cálculo de progresso definido como com base no status
- status_p_complete_changed: >-
- Valor da % de conclusão para o estado '%{status_name}' alterado de %{old_value}% para %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
A partir de agora, a atividade relacionada a links de arquivos (arquivos armazenados em armazenamentos externos) aparecerá aqui na guia Atividade. O seguinte representa a atividade relacionada aos links que já existiam:
@@ -2332,7 +2350,7 @@ pt-BR:
label_workflow: "Fluxo de Trabalho"
label_workflow_plural: "Fluxos de trabalho"
label_workflow_summary: "Sumário"
- label_working_days: "Dias úteis"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 fechado"
other: "%{count} fechados"
@@ -2930,6 +2948,9 @@ pt-BR:
setting_cross_project_work_package_relations: "Permitir relacionamento entre pacotes de trabalho de diferentes projetos"
setting_first_week_of_year: "A primeira semana no ano contém"
setting_date_format: "Data"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Idioma padrão"
setting_default_projects_modules: "Módulos habilitados por padrão para novos projetos"
setting_default_projects_public: "Novos projetos são públicos por padrão"
@@ -2945,6 +2966,12 @@ pt-BR:
setting_feeds_limit: "Limite de conteúdo de feed"
setting_file_max_size_displayed: "Tamanho máximo de arquivos de texto exibidos em linha"
setting_host_name: "Nome do servidor"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "E-mail de ativação expira após"
setting_work_package_done_ratio: "Cálculo de progresso"
setting_work_package_done_ratio_field: "Com base no trabalho"
@@ -3385,12 +3412,12 @@ pt-BR:
additional_privileges_project_or_group: "Poderá ter privilégios adicionais (como membro do projeto ou grupo)"
working_days:
info: >
- Dias que não são selecionados são pulados ao agendar pacotes de trabalho (e não são incluídos na contagem do dia). Estes podem ser substituídos a nível do pacotes de trabalho.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
As datas adicionadas à lista abaixo são consideradas não úteis e ignoradas ao agendar pacotes de trabalho.
change_button: "Alterar dias úteis"
warning: >
- Alterar os dias da semana considerados úteis ou não úteis pode afetar as datas de início e término de todos os pacotes de trabalho em todos os projetos desta instância. Observe que as alterações só são aplicadas após clicar no botão aplicar alterações.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Dias úteis** alterado (%{changes})._
days:
diff --git a/config/locales/crowdin/pt-PT.yml b/config/locales/crowdin/pt-PT.yml
index e0a5723d982e..0efbaeeee1de 100644
--- a/config/locales/crowdin/pt-PT.yml
+++ b/config/locales/crowdin/pt-PT.yml
@@ -298,6 +298,12 @@ pt-PT:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Atualmente, não existem tipos disponíveis.
form:
@@ -446,12 +452,20 @@ pt-PT:
Nenhum atributo pode ser alterado com a exceção do estado.
Nota: Valores herdados (ex: por crianças ou relações) ainda serão aplicados.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Clique para atribuir ou alterar a cor deste status.
É mostrada no botão de status e pode ser usada para destacar os pacotes de trabalho na tabela.
index:
no_results_title_text: Atualmente, não existem estados de pacote de trabalho.
no_results_content_text: Adicione um novo estado
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Claro"
light_high_contrast: "Contraste alto claro"
@@ -621,6 +635,7 @@ pt-PT:
status:
is_closed: "Tarefa fechada"
is_readonly: "Pacote de trabalho só de leitura"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Notas"
member:
@@ -957,6 +972,14 @@ pt-PT:
base:
working_days_are_missing: "Pelo menos um dia da semana deve ser definido como dia útil."
previous_working_day_changes_unprocessed: "As alterações anteriores na configuração de dias úteis ainda não foram aplicadas."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1141,18 +1164,6 @@ pt-PT:
other: "%{count} horas"
updated: "alterado de %{old_value} para %{value}"
logged_for: "Registado para"
- meeting_agenda_item:
- duration:
- added: "definido como %{value}"
- added_html: "definido como %{value}"
- removed: "removido"
- updated: "alterado de %{old_value} para %{value}"
- updated_html: "alterado de %{old_value} para %{value}"
- position:
- updated: "reordenado"
- work_package:
- updated: "alterado de %{old_value} para %{value}"
- updated_html: "alterado de %{old_value} para %{value}"
filter:
changeset: "Conjunto de alterações"
message: "Fóruns"
@@ -1603,6 +1614,12 @@ pt-PT:
pdf_gantt: "PDF Gantt"
image:
omitted: "Imagem não exportada."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1656,7 +1673,7 @@ pt-PT:
dates_changed: "Datas alteradas"
default_attribute_written: "Escrita de atributos só de leitura"
progress_mode_changed_to_status_based: "Cálculo do progresso atualizado"
- status_p_complete_changed: "Estado da % de conclusão alterado"
+ status_changed: "Status '%{status_name}'"
system_update: "Atualização do sistema OpenProject:"
cause_descriptions:
work_package_predecessor_changed_times: por alterações no %{link} antecessor
@@ -1673,8 +1690,9 @@ pt-PT:
working: "%{date} está agora a funcionar"
non_working: "%{date} não está agora a funcionar"
progress_mode_changed_to_status_based: Modo de cálculo do progresso definido como baseado no estado
- status_p_complete_changed: >-
- Valor da % de conclusão para o estado "%{status_name}" alterado de %{old_value}% para %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
A partir de agora, a atividade relacionada a links de arquivos (arquivos armazenados em armazenamentos externos) aparecerá aqui na guia Atividade. O seguinte representa a atividade relacionada aos links que já existiam:
@@ -2331,7 +2349,7 @@ pt-PT:
label_workflow: "Fluxo de trabalho"
label_workflow_plural: "Fluxos de Trabalho"
label_workflow_summary: "Resumo"
- label_working_days: "Dias úteis"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 fechado"
other: "%{count} fechados"
@@ -2928,6 +2946,9 @@ pt-PT:
setting_cross_project_work_package_relations: "Permitir relações entre projectos de pacotes de trabalho"
setting_first_week_of_year: "A primeira semana no ano contém"
setting_date_format: "Data"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Idioma predefinido"
setting_default_projects_modules: "Módulos ativos por predefinição para novos projetos"
setting_default_projects_public: "Projetos novos são públicos por omissão"
@@ -2943,6 +2964,12 @@ pt-PT:
setting_feeds_limit: "Limite de conteúdo feed"
setting_file_max_size_displayed: "Tamanho máximo de ficheiros de texto exibido inline"
setting_host_name: "Nome do host"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "O email de ativação expira após"
setting_work_package_done_ratio: "Cálculo do progresso"
setting_work_package_done_ratio_field: "Baseado no trabalho"
@@ -3384,12 +3411,12 @@ pt-PT:
additional_privileges_project_or_group: "Poderá ter privilégios adicionais (como membro do projeto ou do grupo)"
working_days:
info: >
- Os dias não selecionados são ignorados ao agendar pacotes de trabalho (e não são incluídos na contagem de dias). Podem ser substituídos ao nível dos pacotes de trabalho.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
As datas adicionadas à lista abaixo são consideradas inúteis e ignoradas ao agendar pacotes de trabalho.
change_button: "Alterar dias úteis"
warning: >
- Alterar os dias da semana considerados úteis ou não úteis pode afetar as datas de início e término de todos os pacotes de trabalho em todos os projetos desta instância. Tenha em atenção que as alterações só são aplicadas após clicar no botão Aplicar alterações.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Dias úteis** alterados (%{changes})._
days:
diff --git a/config/locales/crowdin/ro.yml b/config/locales/crowdin/ro.yml
index c513c9d4cb2a..7d14d0d6dcf2 100644
--- a/config/locales/crowdin/ro.yml
+++ b/config/locales/crowdin/ro.yml
@@ -300,6 +300,12 @@ ro:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: În acest moment nu există tipuri disponibile.
form:
@@ -454,12 +460,20 @@ ro:
Nu se poate modifica niciun atribut, cu excepția statutului.
Notă: Valorile moștenite (de exemplu, de la copii sau relații) se vor aplica în continuare.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Faceți click pentru a desemna sau schimba culoarea pentru acest flux de lucru.
Acesta este afișat în butonul de statut și poate fi folosit pentru a evidenția pachetele de lucru din tabel.
index:
no_results_title_text: În acest moment nu există stări pentru pachetele de lucru.
no_results_content_text: Adăugare stare nouă
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -630,6 +644,7 @@ ro:
status:
is_closed: "Pachet de lucru închis"
is_readonly: "Pachet de lucru numai pentru citire"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Mențiuni"
member:
@@ -966,6 +981,14 @@ ro:
base:
working_days_are_missing: "Cel puțin o zi a săptămânii trebuie să fie definită ca zi lucrătoare."
previous_working_day_changes_unprocessed: "Modificările anterioare la configurația din zilele lucrătoare nu au fost încă aplicate."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1158,18 +1181,6 @@ ro:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Seturi de modificări"
message: "Forumuri"
@@ -1638,6 +1649,12 @@ ro:
pdf_gantt: "PDF Gantt"
image:
omitted: "Imaginea nu a fost exportată."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1691,7 +1708,7 @@ ro:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1708,8 +1725,9 @@ ro:
working: "%{date} este acum în funcțiune"
non_working: "%{date} este acum nefuncțională"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2366,7 +2384,7 @@ ro:
label_workflow: "Flux de lucru"
label_workflow_plural: "Fluxuri de lucru"
label_workflow_summary: "Descriere"
- label_working_days: "Zile lucrătoare"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "unul închis"
other: "%{count} închise"
@@ -2967,6 +2985,9 @@ ro:
setting_cross_project_work_package_relations: "Permiteți legături între pachetele de lucru din proiecte diferite"
setting_first_week_of_year: "Prima săptămână din an conține"
setting_date_format: "Dată"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Limbă implicită"
setting_default_projects_modules: "Module activate implicit la creare proiect"
setting_default_projects_public: "Proiectele noi sunt implicit publice"
@@ -2982,6 +3003,12 @@ ro:
setting_feeds_limit: "Limită conținut flux"
setting_file_max_size_displayed: "Numărul maxim de linii afișat în text"
setting_host_name: "Numele serverului"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "E-mailul de activare expiră după"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3424,12 +3451,12 @@ ro:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Modificarea zilelor lucrătoare"
warning: >
- În acest caz, modificarea zilelor săptămânii care sunt considerate zile lucrătoare sau nelucrătoare poate afecta zilele de început și de sfârșit ale tuturor pachetelor de lucru din toate proiectele. Vă rugăm să rețineți că modificările sunt aplicate numai după ce faceți clic pe butonul de aplicare a modificărilor.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Zile lucrătoare** schimbate (%{changes})._
days:
diff --git a/config/locales/crowdin/ru.yml b/config/locales/crowdin/ru.yml
index 2a29340dffeb..a47c7380a783 100644
--- a/config/locales/crowdin/ru.yml
+++ b/config/locales/crowdin/ru.yml
@@ -299,6 +299,12 @@ ru:
is_required_blank_slate:
heading: Требуется во всех проектах
description: Этот атрибут проекта активирован во всех проектах, поскольку установлен флажок «Требуется во всех проектах». Его нельзя отключить для отдельных проектов.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: На данный момент доступных типов нет.
form:
@@ -459,12 +465,20 @@ ru:
Никакие атрибуты не могут быть изменены за исключением статуса.
Примечание strong>: Будут применены унаследованные значения (например, элементов предков или потомков).
+ status_excluded_from_totals_text: |-
+ Отметьте эту опцию, чтобы исключить пакеты работ с этим статусом из итогов Работы,
+ Оставшейся работы и % Завершения в иерархии.
status_color_text: |
Щелкните, чтобы задать или изменить цвет этого статуса.
Этот цвет отображается на кнопке статуса и может использоваться для выделения пакетов работ в таблице.
index:
no_results_title_text: В данный момент статусы пакетов работ отсутствуют.
no_results_content_text: Добавить новый статус
+ headers:
+ is_default: "По умолчанию"
+ is_closed: "Закрыто"
+ is_readonly: "Только для чтения"
+ excluded_from_totals: "Исключено из итогов"
themes:
light: "Светлая"
light_high_contrast: "Светлый высокий контраст"
@@ -636,6 +650,7 @@ ru:
status:
is_closed: "Пакет работ закрыт"
is_readonly: "Пакет работ только для просмотра"
+ excluded_from_totals: "Исключить из расчета итогов в иерархии"
journal:
notes: "Примечания"
member:
@@ -972,6 +987,14 @@ ru:
base:
working_days_are_missing: "По крайней мере, один день недели должен быть определен как рабочий."
previous_working_day_changes_unprocessed: "Предыдущие изменения конфигурации рабочих дней еще не были применены."
+ hours_per_day_are_missing: "Необходимо указать количество часов в день."
+ days_per_week_are_missing: "Необходимо указать количество дней в неделю."
+ days_per_month_are_missing: "Необходимо указать количество дней в месяце."
+ durations_are_not_positive_numbers: "Длительность должна быть положительным числом."
+ hours_per_day_is_out_of_bounds: "Количество часов в день не может быть больше 24"
+ days_per_week_is_out_of_bounds: "Количество дней в неделю не может быть больше 7"
+ days_per_month_is_out_of_bounds: "Количество дней в месяце не может быть больше 31"
+ days_per_week_and_days_per_month_are_inconsistent: "Количество дней в неделю и количество дней в месяц должны быть постоянными."
time_entry:
attributes:
hours:
@@ -1172,18 +1195,6 @@ ru:
other: "%{count} часов"
updated: "изменено с %{old_value} на %{value}"
logged_for: "Зарегистрирован для"
- meeting_agenda_item:
- duration:
- added: "установлено в %{value}"
- added_html: "установлено в %{value}"
- removed: "удалено"
- updated: "изменено с %{old_value} на %{value}"
- updated_html: "изменено с %{old_value} на %{value}"
- position:
- updated: "переупорядочено"
- work_package:
- updated: "изменено с %{old_value} на %{value}"
- updated_html: "изменено с %{old_value} на %{value}"
filter:
changeset: "Наборы изменений"
message: "Форумы"
@@ -1237,7 +1248,7 @@ ru:
password: "Пароль"
priority: "Приоритет"
project: "Проект"
- responsible: "Подотчетный"
+ responsible: "Ответственный"
role: "Роль"
roles: "Роли"
start_date: "Дата начала"
@@ -1670,6 +1681,12 @@ ru:
pdf_gantt: "Диаграмма Гантта в PDF"
image:
omitted: "Изображение не экспортировано."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: ч
days: д
@@ -1723,7 +1740,7 @@ ru:
dates_changed: "Даты изменены"
default_attribute_written: "Запись атрибутов со свойством \"только для чтения\""
progress_mode_changed_to_status_based: "Расчет прогресса обновлен"
- status_p_complete_changed: "Статус \"% завершения\" изменен"
+ status_changed: "Статус '%{status_name}'"
system_update: "Обновление системы OpenProject:"
cause_descriptions:
work_package_predecessor_changed_times: внесением изменений в предшественника %{link}
@@ -1740,8 +1757,9 @@ ru:
working: "%{date} сейчас рабочий"
non_working: "%{date} теперь нерабочий"
progress_mode_changed_to_status_based: Расчет прогресса установлен в режим "На основе статуса"
- status_p_complete_changed: >-
- "% завершения" для статуса '%{status_name}' изменено с %{old_value}% на %{new_value}%
+ status_excluded_from_totals_set_to_false_message: теперь включено в иерархию итогов
+ status_excluded_from_totals_set_to_true_message: теперь исключено из иерархии итогов
+ status_percent_complete_changed: "% завершения изменен с %{old_value}% на %{new_value}%"
system_update:
file_links_journal: >
Теперь на вкладке Активность появится активность, связанная со ссылками файлов (файлы, хранящиеся во внешних хранилищах). Ниже описывается деятельность по уже существующим ссылкам:
@@ -2398,7 +2416,7 @@ ru:
label_workflow: "Рабочий поток"
label_workflow_plural: "Рабочие потоки"
label_workflow_summary: "Сводка"
- label_working_days: "Рабочие дни"
+ label_working_days_and_hours: "Рабочие дни и часы"
label_x_closed_work_packages_abbr:
one: "1 закрыто"
other: "%{count} закрыто"
@@ -2481,7 +2499,7 @@ ru:
reason:
watched: "Просмотрено"
assigned: "Назначено"
- responsible: "Подотчетный"
+ responsible: "Ответственный"
mentioned: "Упомянутые"
shared: "Общий доступ"
subscribed: "все"
@@ -2999,6 +3017,9 @@ ru:
setting_cross_project_work_package_relations: "Разрешить перектестные связи пакетов работ проекта"
setting_first_week_of_year: "Первая неделя в году содержит"
setting_date_format: "Дата"
+ setting_days_per_month: "Количество дней в месяце"
+ setting_days_per_month_explanation: >-
+ Это определяет, что считается "месяцем" при более естественном отображении продолжительности (например, если месяц 20 дней, то 60 дней будет 3 месяца).
setting_default_language: "Язык по умолчанию"
setting_default_projects_modules: "По умолчанию доступные в новых проектах модули"
setting_default_projects_public: "По умолчанию новые проекты видимы всем"
@@ -3014,6 +3035,12 @@ ru:
setting_feeds_limit: "Предел содержимого новостной ленты"
setting_file_max_size_displayed: "Максимальная длина строки текстовых файлов"
setting_host_name: "Имя компьютера в сети"
+ setting_hours_per_day: "Количество часов в день"
+ setting_hours_per_day_explanation: >-
+ Это определяет, что считается "днем" при более естественном отображении продолжительности (например, если день 8 часов, то 32 часа будет 4 дня).
+ setting_days_per_week: "Количество дней в неделю"
+ setting_days_per_week_explanation: >-
+ Это определяет, что считается "неделей" при более естественном отображении продолжительности (например, если в неделю 5 дней, то 15 дней будет 3 недели).
setting_invitation_expiration_days: "Действие письма активации истекает после"
setting_work_package_done_ratio: "Режим расчета прогресса"
setting_work_package_done_ratio_field: "На основе трудозатрат"
@@ -3461,7 +3488,7 @@ ru:
Даты, добавленные в список ниже, считаются нерабочими и пропускаются при планировании пакетов работ.
change_button: "Изменить рабочие дни"
warning: >
- Изменение того, какие дни недели считаются рабочими или нерабочими, может повлиять на дни начала и окончания всех рабочих пакетов во всех проектах в данной системе. Пожалуйста, обратите внимание, что изменения вступят в силу после того, как вы нажмете на кнопку применить.
+ Изменение дней недели, считающихся рабочими или нерабочими днями, может повлиять на начало и завершение всех пакетов работ во всех проектах.
journal_note:
changed: _**Рабочие дни** изменены (%{changes})._
days:
diff --git a/config/locales/crowdin/rw.yml b/config/locales/crowdin/rw.yml
index b2d1a3cb83fb..0b0fe0718418 100644
--- a/config/locales/crowdin/rw.yml
+++ b/config/locales/crowdin/rw.yml
@@ -300,6 +300,12 @@ rw:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: There are currently no types available.
form:
@@ -448,12 +454,20 @@ rw:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: There are currently no work package statuses.
no_results_content_text: Add a new status
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -623,6 +637,7 @@ rw:
status:
is_closed: "Work package closed"
is_readonly: "Work package read-only"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Notes"
member:
@@ -959,6 +974,14 @@ rw:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1143,18 +1166,6 @@ rw:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Changesets"
message: "Forums"
@@ -1605,6 +1616,12 @@ rw:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1658,7 +1675,7 @@ rw:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1675,8 +1692,9 @@ rw:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2333,7 +2351,7 @@ rw:
label_workflow: "Workflow"
label_workflow_plural: "Workflows"
label_workflow_summary: "Summary"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 closed"
other: "%{count} closed"
@@ -2933,6 +2951,9 @@ rw:
setting_cross_project_work_package_relations: "Allow cross-project work package relations"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "Date"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Default language"
setting_default_projects_modules: "Default enabled modules for new projects"
setting_default_projects_public: "New projects are public by default"
@@ -2948,6 +2969,12 @@ rw:
setting_feeds_limit: "Feed content limit"
setting_file_max_size_displayed: "Max size of text files displayed inline"
setting_host_name: "Host name"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3389,12 +3416,12 @@ rw:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/si.yml b/config/locales/crowdin/si.yml
index 3342ecc7fa8e..171a4a3a8b3b 100644
--- a/config/locales/crowdin/si.yml
+++ b/config/locales/crowdin/si.yml
@@ -300,6 +300,12 @@ si:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: දැනට වර්ග නොමැත.
form:
@@ -448,12 +454,20 @@ si:
තත්ත්වය හැරුණු විට කිසිදු ගුණාංගයක් වෙනස් කළ නොහැක.
සටහන: උරුම වූ වටිනාකම් (උදා: දරුවන් හෝ සබඳතා වලින්) තවමත් අදාළ වේ.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
මෙම තත්වයේ වර්ණය පැවරීම හෝ වෙනස් කිරීම සඳහා ක්ලික් කරන්න.
එය තත්ව බොත්තමෙහි පෙන්වා ඇති අතර වගුවේ වැඩ පැකේජ ඉස්මතු කිරීම සඳහා භාවිතා කළ හැකිය.
index:
no_results_title_text: දැනට වැඩ පැකේජ තත්වයන් නොමැත.
no_results_content_text: නව තත්වයක් එකතුකරන්න
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -623,6 +637,7 @@ si:
status:
is_closed: "වැඩ පැකේජය වසා"
is_readonly: "වැඩ පැකේජය කියවීමට-පමණි"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "සටහන්"
member:
@@ -959,6 +974,14 @@ si:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1143,18 +1166,6 @@ si:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "වෙනස්කම්"
message: "සංසද"
@@ -1605,6 +1616,12 @@ si:
pdf_gantt: "PDF Gantt"
image:
omitted: "රූපය අපනයනය කර නැත."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1658,7 +1675,7 @@ si:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1675,8 +1692,9 @@ si:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2333,7 +2351,7 @@ si:
label_workflow: "කාර්ය ප්රවාහ"
label_workflow_plural: "වැඩ ප්රවාහ"
label_workflow_summary: "සාරාංශය"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 වසා"
other: "%{count} වසා"
@@ -2933,6 +2951,9 @@ si:
setting_cross_project_work_package_relations: "හරස් ව්යාපෘති වැඩ පැකේජ සබඳතා ඉඩ දෙන්න"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "දිනය"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "පෙරනිමි භාෂාව"
setting_default_projects_modules: "නව ව්යාපෘති සඳහා පෙරනිමි සක්රීය මොඩියුල"
setting_default_projects_public: "නව ව්යාපෘති පෙරනිමියෙන් පොදු වේ"
@@ -2948,6 +2969,12 @@ si:
setting_feeds_limit: "අන්තර්ගත සීමාව සංග්රහ"
setting_file_max_size_displayed: "පේළිගත ප්රදර්ශනය පෙළ ගොනු උපරිම ප්රමාණය"
setting_host_name: "සත්කාරක නාමය"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "සක්රිය කිරීමේ විද්යුත් තැපෑල කල් ඉකුත් වේ"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3389,12 +3416,12 @@ si:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/sk.yml b/config/locales/crowdin/sk.yml
index 2c904aaa6bd4..cbc306c99bd1 100644
--- a/config/locales/crowdin/sk.yml
+++ b/config/locales/crowdin/sk.yml
@@ -300,6 +300,12 @@ sk:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Momentálne nie sú k dispozícii žiadne typy.
form:
@@ -460,12 +466,20 @@ sk:
Nie je možné meniť žiadne atribúty s výnimkou stavu samotného.
Poznámka: zdedené hodnoty (napr. z podradených alebo ďalších relácií) budú platné i naďalej.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Kliknite na položku priradiť alebo zmeniť farbu tejto priority.
Zobrazuje sa v tlačidle stavu a dá sa použiť na zvýraznenie pracovných balíčkov v tabuľke.
index:
no_results_title_text: Momentálne nie sú žiadne stavy pracovného balíka.
no_results_content_text: Pridať nový stav
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -637,6 +651,7 @@ sk:
status:
is_closed: "Uzatvorený pracovný balíček"
is_readonly: "Pracovný balíček iba na čítanie"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Poznámky"
member:
@@ -973,6 +988,14 @@ sk:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1173,18 +1196,6 @@ sk:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Sady zmien"
message: "Diskusie"
@@ -1671,6 +1682,12 @@ sk:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1724,7 +1741,7 @@ sk:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1741,8 +1758,9 @@ sk:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2399,7 +2417,7 @@ sk:
label_workflow: "Pracovný postup"
label_workflow_plural: "Pracovné postupy"
label_workflow_summary: "Zhrnutie"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 uzatvorený"
other: "%{count} uzatvorených"
@@ -3002,6 +3020,9 @@ sk:
setting_cross_project_work_package_relations: "Povoliť prepojenia úloh naprieč projektmi"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "Dátum"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Predvolený jazyk"
setting_default_projects_modules: "Predvolené moduly novovytváraných projektov"
setting_default_projects_public: "Nové projekty nastaviť ako verejné"
@@ -3017,6 +3038,12 @@ sk:
setting_feeds_limit: "Limit obsahu informačných kanálov"
setting_file_max_size_displayed: "Maximálna veľkosť textových súborov zobrazených priamo na stránke"
setting_host_name: "Názov serveru (Host name)"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3460,12 +3487,12 @@ sk:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/sl.yml b/config/locales/crowdin/sl.yml
index 96c95eff89a7..11630979b0c7 100644
--- a/config/locales/crowdin/sl.yml
+++ b/config/locales/crowdin/sl.yml
@@ -299,6 +299,12 @@ sl:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Trenutno ni na voljo nobenih vrst.
form:
@@ -458,12 +464,20 @@ sl:
Označite to možnost, da delovne pakete s tem statusom označite kot "samo za branje".
Nobenih lastnosti ni mogoče spremeniti, razen statusa.
Note: Prevzete vrednosti (npr. od otrok ali odnosov) bodo še vedno veljale.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Kliknite, če želite dodeliti ali spremeniti barvo tega stanja.
Prikazana je v gumbu stanja in se lahko uporablja za označevanje delovnih paketov v tabeli.
index:
no_results_title_text: Trenutno ni statusov delovnega paketa.
no_results_content_text: Dodaj nov status
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -634,6 +648,7 @@ sl:
status:
is_closed: "Zahtevek zaprt"
is_readonly: "Zahtevek \"samo za branje\""
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Opombe"
member:
@@ -970,6 +985,14 @@ sl:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1170,18 +1193,6 @@ sl:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Zapisi sprememb"
message: "Forumi"
@@ -1668,6 +1679,12 @@ sl:
pdf_gantt: "PDF Gantt"
image:
omitted: "Slika ni izvožena."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1721,7 +1738,7 @@ sl:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1738,8 +1755,9 @@ sl:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2396,7 +2414,7 @@ sl:
label_workflow: "Potek dela"
label_workflow_plural: "Potek dela"
label_workflow_summary: "Povzetek"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 zaprt"
other: "%{count} zaprtih"
@@ -2999,6 +3017,9 @@ sl:
setting_cross_project_work_package_relations: "Dovoli povezave delovnih paketov od različnih projektov"
setting_first_week_of_year: "Prvi teden v letu vsebuje"
setting_date_format: "Datum"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Privzeti jezik"
setting_default_projects_modules: "Privzeti omogočeni moduli za nove projekte"
setting_default_projects_public: "Novi projekti so privzeto javni"
@@ -3014,6 +3035,12 @@ sl:
setting_feeds_limit: "Omejitev vsebine vira"
setting_file_max_size_displayed: "Največja velikost besedilnih datotek, prikazanih v vrstici"
setting_host_name: "Ime gostitelja"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "aktivacijsko e-poštno sporočilo poteče po"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3457,12 +3484,12 @@ sl:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/sr.yml b/config/locales/crowdin/sr.yml
index 9e2414994e02..8630a3e6567b 100644
--- a/config/locales/crowdin/sr.yml
+++ b/config/locales/crowdin/sr.yml
@@ -300,6 +300,12 @@ sr:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: There are currently no types available.
form:
@@ -454,12 +460,20 @@ sr:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: There are currently no work package statuses.
no_results_content_text: Add a new status
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -630,6 +644,7 @@ sr:
status:
is_closed: "Work package closed"
is_readonly: "Work package read-only"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Notes"
member:
@@ -966,6 +981,14 @@ sr:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1158,18 +1181,6 @@ sr:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Changesets"
message: "Forums"
@@ -1638,6 +1649,12 @@ sr:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1691,7 +1708,7 @@ sr:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1708,8 +1725,9 @@ sr:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2366,7 +2384,7 @@ sr:
label_workflow: "Workflow"
label_workflow_plural: "Workflows"
label_workflow_summary: "Summary"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 closed"
other: "%{count} closed"
@@ -2968,6 +2986,9 @@ sr:
setting_cross_project_work_package_relations: "Allow cross-project work package relations"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "Date"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Default language"
setting_default_projects_modules: "Default enabled modules for new projects"
setting_default_projects_public: "New projects are public by default"
@@ -2983,6 +3004,12 @@ sr:
setting_feeds_limit: "Feed content limit"
setting_file_max_size_displayed: "Max size of text files displayed inline"
setting_host_name: "Host name"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3425,12 +3452,12 @@ sr:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/sv.yml b/config/locales/crowdin/sv.yml
index bf14b7b519ef..357930892064 100644
--- a/config/locales/crowdin/sv.yml
+++ b/config/locales/crowdin/sv.yml
@@ -300,6 +300,12 @@ sv:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Det finns för närvarande inga typer tillgängliga.
form:
@@ -447,12 +453,20 @@ sv:
Välj detta val för att markera arbetspaket med denna status som skrivskyddade.
Inga attribut kan ändras förutom status.
NoteraÄrvda värden (t. ex. från barn eller relationer) kommer fortfarande gälla.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Välj för att tilldela eller ändra färgen för denna status.
Den visas i statusknappen och och kan användas för markering av arbetspaket i tabellen.
index:
no_results_title_text: Det finns för närvarande inga statusar för arbetspaket.
no_results_content_text: Lägg till ny status
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Ljust"
light_high_contrast: "Light high contrast"
@@ -622,6 +636,7 @@ sv:
status:
is_closed: "Arbetspaket stängt"
is_readonly: "Skrivskyddat arbetspaket"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Anteckningar"
member:
@@ -958,6 +973,14 @@ sv:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1142,18 +1165,6 @@ sv:
other: "%{count} timmar"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Uppdateringar"
message: "Forum"
@@ -1604,6 +1615,12 @@ sv:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1657,7 +1674,7 @@ sv:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1674,8 +1691,9 @@ sv:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2332,7 +2350,7 @@ sv:
label_workflow: "Arbetsflöde"
label_workflow_plural: "Arbetsflöden"
label_workflow_summary: "Sammanfattning"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "en stängd"
other: "%{count} stängda"
@@ -2930,6 +2948,9 @@ sv:
setting_cross_project_work_package_relations: "Tillåt relationer mellan arbetspaket i olika projekt"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "Datum"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Standardspråk"
setting_default_projects_modules: "Standardmoduler för nya projekt"
setting_default_projects_public: "Nya projekt är offentliga som standard"
@@ -2945,6 +2966,12 @@ sv:
setting_feeds_limit: "Innehållsbegränsning på Flöden"
setting_file_max_size_displayed: "Maxstorlek på textfiler som visas inline"
setting_host_name: "Värdnamn"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Aktiveringsmail upphör efter"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3385,12 +3412,12 @@ sv:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/th.yml b/config/locales/crowdin/th.yml
index 288697219992..ed492f465c9a 100644
--- a/config/locales/crowdin/th.yml
+++ b/config/locales/crowdin/th.yml
@@ -300,6 +300,12 @@ th:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: There are currently no types available.
form:
@@ -442,12 +448,20 @@ th:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: There are currently no work package statuses.
no_results_content_text: เพิ่มสถานะใหม่
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -616,6 +630,7 @@ th:
status:
is_closed: "ปิดชุดภารกิจแล้ว"
is_readonly: "Work package read-only"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "หมายเหตุ"
member:
@@ -952,6 +967,14 @@ th:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1128,18 +1151,6 @@ th:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "ชุดการเปลี่ยนแปลง"
message: "กระทู้"
@@ -1572,6 +1583,12 @@ th:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1625,7 +1642,7 @@ th:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1642,8 +1659,9 @@ th:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2300,7 +2318,7 @@ th:
label_workflow: "กระบวนการทำงาน"
label_workflow_plural: "กระบวนการทำงาน"
label_workflow_summary: "สรุป"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 closed"
other: "ปิดแล้ว %{count}"
@@ -2898,6 +2916,9 @@ th:
setting_cross_project_work_package_relations: "อนุญาติให้มีความเกี่ยวข้องกันระหว่างชุดภารกิจในโครงการ"
setting_first_week_of_year: "สัปดาห์แรกของปี ประกอบด้วย"
setting_date_format: "วันที่"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "ภาษาเริ่มต้น"
setting_default_projects_modules: "ค่าเริ่มต้นของโมดูลที่เปิดใช้สำหรับโครงการใหม่"
setting_default_projects_public: "โดยเริ่มแรก โครงการใหม่จะเป็นสาธารณะ"
@@ -2913,6 +2934,12 @@ th:
setting_feeds_limit: "จำกัดเนื้อหาของ Feed"
setting_file_max_size_displayed: "ความยาวสูงสุดของไฟล์ตัวอักษรแสดงในบรรทัด"
setting_host_name: "ชื่อโฮสต์"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3353,12 +3380,12 @@ th:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/tr.yml b/config/locales/crowdin/tr.yml
index b3e942d244d4..f84e684d5afa 100644
--- a/config/locales/crowdin/tr.yml
+++ b/config/locales/crowdin/tr.yml
@@ -300,6 +300,12 @@ tr:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Şu anda hiçbir tip mevcut değil.
form:
@@ -448,12 +454,20 @@ tr:
Durum haricindeki başka özellikler değiştirilemez.
Uyarı: Devralınan değerler (örneğin; çocuklardan ve bağlantılardan) hala geçerli olacaktır.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Bu durumun rengini atamak veya değiştirmek için tıklayın.
Durum düğmesinde gösterilir ve tablodaki iş paketlerini vurgulamak için kullanılabilir.
index:
no_results_title_text: Şu anda çalışma paketi durumu yok.
no_results_content_text: Yeni durum ekle
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -622,6 +636,7 @@ tr:
status:
is_closed: "İş paketi kapalı"
is_readonly: "İş paketi salt okunur"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Notlar"
member:
@@ -958,6 +973,14 @@ tr:
base:
working_days_are_missing: "Haftanın en az bir günü iş günü olarak tanımlanmalıdır."
previous_working_day_changes_unprocessed: "Çalışma günleri yapılandırmasında yapılan önceki değişiklikler henüz uygulanmadı."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1142,18 +1165,6 @@ tr:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Değişiklik Listeleri"
message: "Forumlar"
@@ -1604,6 +1615,12 @@ tr:
pdf_gantt: "PDF Gantt"
image:
omitted: "Görüntü dışa aktarılmadı."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1657,7 +1674,7 @@ tr:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1674,8 +1691,9 @@ tr:
working: "%{date} artık çalışma günü"
non_working: "%{date} artık çalışılmayan tarih"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2332,7 +2350,7 @@ tr:
label_workflow: "İş akışı"
label_workflow_plural: "İş Akışları"
label_workflow_summary: "Özet"
- label_working_days: "İş Günleri"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 kapalı"
other: "%{count} kapatıldı"
@@ -2929,6 +2947,9 @@ tr:
setting_cross_project_work_package_relations: "Projeler arası iş paketi ilişkilerine izin ver"
setting_first_week_of_year: "Yılın ilk haftası"
setting_date_format: "Tarih"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Varsayılan dil"
setting_default_projects_modules: "Yeni projeler için varsayılan etkin modüller"
setting_default_projects_public: "Yeni projeler varsayılan olarak herkese açık"
@@ -2944,6 +2965,12 @@ tr:
setting_feeds_limit: "Besleme içeriği sınırı"
setting_file_max_size_displayed: "Satır içi görüntülenen maksimum metin dosyası boyutu"
setting_host_name: "Ana bilgisayar adı"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Etkinleştirme e-postasının süresi doluyor"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3384,12 +3411,12 @@ tr:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "İş günlerini değiştir"
warning: >
- Haftanın hangi günlerinin iş günü veya tatil günü olarak kabul edileceğini değiştirmek, bu durumda tüm projelerdeki tüm iş paketlerinin başlangıç ve bitiş günlerini etkileyebilir. Değişikliklerin yalnızca siz değişiklikleri kaydet düğmesine tıkladıktan sonra uygulanacağını lütfen unutmayın.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Çalışma günleri** değişti (%{changes})._
days:
diff --git a/config/locales/crowdin/uk.yml b/config/locales/crowdin/uk.yml
index d38639466270..cbd580431a6b 100644
--- a/config/locales/crowdin/uk.yml
+++ b/config/locales/crowdin/uk.yml
@@ -295,6 +295,12 @@ uk:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Наразі немає доступних типів.
form:
@@ -455,12 +461,20 @@ uk:
Жоден атрибут не можуть бути змінені за виключенням статусу.
Примітки: Будуть застосовані успадковані значення (наприклад, елементів попередників чи нащадків).
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Натисніть, щоб призначити або змінити колір цього статусу.
Він відображається в кнопці стану і може використовуватися для виділення робочих пакетів у таблиці.
index:
no_results_title_text: Наразі немає статусів робочих пакетів.
no_results_content_text: Додати новий статус
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Світла"
light_high_contrast: "Світла, високий контраст"
@@ -632,6 +646,7 @@ uk:
status:
is_closed: "Робочий пакет закритий"
is_readonly: "Пакет робіт лише для перегляду"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Нотатки"
member:
@@ -968,6 +983,14 @@ uk:
base:
working_days_are_missing: "Принаймні один день тижня має бути визначено як робочий."
previous_working_day_changes_unprocessed: "Попередні зміни конфігурації робочих днів ще не застосовано."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1168,18 +1191,6 @@ uk:
other: "%{count} год"
updated: "змінено з %{old_value} на %{value}"
logged_for: "Зареєстровано для"
- meeting_agenda_item:
- duration:
- added: "встановлено значення %{value}"
- added_html: "встановлено значення %{value}"
- removed: "вилучено"
- updated: "змінено %{old_value} на %{value}"
- updated_html: "змінено з %{old_value} на %{value}"
- position:
- updated: "перевпорядковано"
- work_package:
- updated: "змінено з %{old_value} на %{value}"
- updated_html: "змінено з %{old_value} на %{value}"
filter:
changeset: "Набори змін"
message: "Форуми"
@@ -1666,6 +1677,12 @@ uk:
pdf_gantt: "Діаграма Ґанта (PDF)"
image:
omitted: "Зображення не експортовано."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: г
days: д
@@ -1719,7 +1736,7 @@ uk:
dates_changed: "Дати змінено"
default_attribute_written: "Атрибути лише для читання записано"
progress_mode_changed_to_status_based: "Обчислення прогресу оновлено"
- status_p_complete_changed: "Значення параметра «% завершення» змінено"
+ status_changed: "Status '%{status_name}'"
system_update: "Оновлення системи OpenProject"
cause_descriptions:
work_package_predecessor_changed_times: внесенням змін у попередній елемент %{link}
@@ -1736,8 +1753,9 @@ uk:
working: "%{date} – зараз робочий день"
non_working: "%{date} – зараз неробочий день"
progress_mode_changed_to_status_based: Установлено режим обчислення прогресу на основі статусу
- status_p_complete_changed: >-
- Значення параметра «% завершення» для статусу «%{status_name}» змінилося з %{old_value} на %{new_value}
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
Тепер дії, пов’язані з посиланнями на файли (файли, що зберігаються в зовнішніх сховищах), з’являтимуться на вкладці «Активність». Наявні дії, пов’язані із посиланнями:
@@ -2394,7 +2412,7 @@ uk:
label_workflow: "Робочий процес"
label_workflow_plural: "Робочі процеси"
label_workflow_summary: "Резюме"
- label_working_days: "Робочі дні"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 закрита"
other: "%{count} закритих"
@@ -2995,6 +3013,9 @@ uk:
setting_cross_project_work_package_relations: "Дозволити взаємозв'язок між робочими пакетами і проектами"
setting_first_week_of_year: "Перший тиждень у році містить"
setting_date_format: "Дата"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Мова за замовчуванням"
setting_default_projects_modules: "Включені по замовчуванню модулі для нових проектів"
setting_default_projects_public: "Нові проекти є загальнодоступними"
@@ -3010,6 +3031,12 @@ uk:
setting_feeds_limit: "Обмеження вмісту каналу"
setting_file_max_size_displayed: "Максимальний розмір текстового файлу для відображення"
setting_host_name: "Ім'я хоста"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Повідомлення про активацію закінчується"
setting_work_package_done_ratio: "Обчислення прогресу"
setting_work_package_done_ratio_field: "На основі роботи"
@@ -3452,12 +3479,12 @@ uk:
additional_privileges_project_or_group: "Може мати додаткові повноваження (як учасник проєкту або групи)"
working_days:
info: >
- Під час планування пакетів робіт невибрані дні пропускаються й не включаються в кількість днів. Це налаштування можна змінити на рівні пакета робіт.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Під час планування пакетів робіт дати, додані в список нижче, вважаються неробочим днями й пропускаються.
change_button: "Змінити робочі дні"
warning: >
- Змінення днів тижня, які вважаються робочими або неробочими, може вплинути на дати початку й закінчення всіх пакетів робіт в усіх проєктах цього екземпляра. Зверніть увагу: зміни застосовуються лише після натискання кнопки «Застосувати зміни».
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Робочі дні** змінено (%{changes})._
days:
diff --git a/config/locales/crowdin/uz.yml b/config/locales/crowdin/uz.yml
index dc3703b852f9..6d8f0a386eaa 100644
--- a/config/locales/crowdin/uz.yml
+++ b/config/locales/crowdin/uz.yml
@@ -300,6 +300,12 @@ uz:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: There are currently no types available.
form:
@@ -448,12 +454,20 @@ uz:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: There are currently no work package statuses.
no_results_content_text: Add a new status
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -623,6 +637,7 @@ uz:
status:
is_closed: "Work package closed"
is_readonly: "Work package read-only"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Notes"
member:
@@ -959,6 +974,14 @@ uz:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1143,18 +1166,6 @@ uz:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Changesets"
message: "Forums"
@@ -1605,6 +1616,12 @@ uz:
pdf_gantt: "PDF Gantt"
image:
omitted: "Image not exported."
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1658,7 +1675,7 @@ uz:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1675,8 +1692,9 @@ uz:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2333,7 +2351,7 @@ uz:
label_workflow: "Workflow"
label_workflow_plural: "Workflows"
label_workflow_summary: "Summary"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 closed"
other: "%{count} closed"
@@ -2933,6 +2951,9 @@ uz:
setting_cross_project_work_package_relations: "Allow cross-project work package relations"
setting_first_week_of_year: "First week in year contains"
setting_date_format: "Date"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Default language"
setting_default_projects_modules: "Default enabled modules for new projects"
setting_default_projects_public: "New projects are public by default"
@@ -2948,6 +2969,12 @@ uz:
setting_feeds_limit: "Feed content limit"
setting_file_max_size_displayed: "Max size of text files displayed inline"
setting_host_name: "Host name"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3389,12 +3416,12 @@ uz:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/vi.yml b/config/locales/crowdin/vi.yml
index 4f78dcd8abae..564d0b0fa406 100644
--- a/config/locales/crowdin/vi.yml
+++ b/config/locales/crowdin/vi.yml
@@ -302,6 +302,12 @@ vi:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: Không có phân loại.
form:
@@ -444,12 +450,20 @@ vi:
No attributes can be changed with the exception of the status.
Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: There are currently no work package statuses.
no_results_content_text: Thêm trạng thái mới
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
light_high_contrast: "Light high contrast"
@@ -618,6 +632,7 @@ vi:
status:
is_closed: "Work package đã đóng"
is_readonly: "Work package chỉ đọc"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "Ghi chú"
member:
@@ -954,6 +969,14 @@ vi:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1130,18 +1153,6 @@ vi:
other: "%{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Nhóm thay đổi"
message: "Diễn đàn"
@@ -1574,6 +1585,12 @@ vi:
pdf_gantt: "PDF Gantt"
image:
omitted: "Hình ảnh không được xuất"
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: h
days: d
@@ -1627,7 +1644,7 @@ vi:
dates_changed: "Dates changed"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "Progress calculation updated"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject system update:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1644,8 +1661,9 @@ vi:
working: "%{date} is now working"
non_working: "%{date} is now non-working"
progress_mode_changed_to_status_based: Progress calculation mode set to status-based
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2302,7 +2320,7 @@ vi:
label_workflow: "Quy trình làm việc"
label_workflow_plural: "Quy trình làm việc"
label_workflow_summary: "Tóm tắt"
- label_working_days: "Working days"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 đóng"
other: "%{count} đóng"
@@ -2900,6 +2918,9 @@ vi:
setting_cross_project_work_package_relations: "Allow cross-project work package relations"
setting_first_week_of_year: "Tuần đầu tiên trong năm"
setting_date_format: "Ngày"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Default language"
setting_default_projects_modules: "Default enabled modules for new projects"
setting_default_projects_public: "New projects are public by default"
@@ -2915,6 +2936,12 @@ vi:
setting_feeds_limit: "Feed content limit"
setting_file_max_size_displayed: "Max size of text files displayed inline"
setting_host_name: "Host name"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3354,12 +3381,12 @@ vi:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance. Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/crowdin/zh-CN.yml b/config/locales/crowdin/zh-CN.yml
index 032202d06103..8c5a95a36f1c 100644
--- a/config/locales/crowdin/zh-CN.yml
+++ b/config/locales/crowdin/zh-CN.yml
@@ -263,7 +263,7 @@ zh-CN:
my: "我的项目"
favored: "收藏的项目"
archived: "归档项目"
- public: "Public project lists"
+ public: "公开项目列表"
my_private: "我的私有项目列表"
new:
placeholder: "新项目列表"
@@ -291,12 +291,18 @@ zh-CN:
actions:
label_enable_single: "在此项目中处于活动状态,点击禁用"
label_disable_single: "在此项目中未启用,点击启用"
- deactivate_for_project: "Deactivate for this project"
+ deactivate_for_project: "停用此项目"
label_enable_all: "全部启用"
label_disable_all: "全部禁用"
is_required_blank_slate:
- heading: Required in all projects
- description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ heading: 所有项目中需要
+ description: 此项目属性已在所有项目中激活,因为选中了“所有项目中需要”的选项。它在单个项目中不能被停用。
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: 目前有可用的类型。
form:
@@ -314,11 +320,11 @@ zh-CN:
success: "已保存修改后的列表"
failure: "无法保存修改后的列表: %{errors}"
publish:
- success: "The list has been made public"
- failure: "The list cannot be made public: %{errors}"
+ success: "此列表已设为公开"
+ failure: "此列表不能设为公开:%{errors}"
unpublish:
- success: "The list has been made private"
- failure: "The list cannot be made private: %{errors}"
+ success: "此列表已被设为私有"
+ failure: "此列表不能被设为私有:%{errors}"
can_be_saved: "列表已修改:"
can_be_saved_as: "修改内容只能保存在新列表中。"
members:
@@ -439,12 +445,20 @@ zh-CN:
除状态外,不能更改任何属性。
注:继承值(例如,来自子级或关系的值)仍然适用。
+ status_excluded_from_totals_text: |-
+ 选中此选项可将具有此状态的工作包排除在层次结构中的 "工时"、"
+ 剩余工时 "和 "完成百分比 "总数之外。
status_color_text: |
单击可以分配或更改此状态的颜色。
颜色显示在状态按钮中,可用于突出显示表中的工作包。
index:
no_results_title_text: 目前没有工作包状态。
no_results_content_text: 添加新的状态
+ headers:
+ is_default: "默认"
+ is_closed: "已关闭"
+ is_readonly: "只读"
+ excluded_from_totals: "不包括在总计中"
themes:
light: "浅色"
light_high_contrast: "浅色高对比度"
@@ -612,6 +626,7 @@ zh-CN:
status:
is_closed: "工作包已关闭"
is_readonly: "只读工作包"
+ excluded_from_totals: "从层次结构的总计中排除"
journal:
notes: "备注"
member:
@@ -752,7 +767,7 @@ zh-CN:
before_or_equal_to: "必须在早于或等于 %{date}"
blank: "不能为空。"
blank_nested: "需要设置属性“%{property}”。"
- cannot_delete_mapping: "is required. Cannot be deleted."
+ cannot_delete_mapping: "必需项,不能删除"
cant_link_a_work_package_with_a_descendant: "工作包无法链接到它的子任务之一。"
circular_dependency: "这种关系将创建循环依赖项。"
confirmation: "不匹配 %{attribute}。"
@@ -913,8 +928,8 @@ zh-CN:
nonexistent: "列“%{column}”不存在。"
format: "%{message}"
group_by_hierarchies_exclusive: "与按照“%{group_by}”分组的组互相排斥。您无法将它们都激活。"
- can_only_be_modified_by_owner: "The query can only be modified by its owner."
- need_permission_to_modify_public_query: "You cannot modify a public query."
+ can_only_be_modified_by_owner: "查询只能由其所有者修改"
+ need_permission_to_modify_public_query: "您不能修改公开查询"
filters:
custom_fields:
inexistent: "过滤器没有自定义字段"
@@ -948,6 +963,14 @@ zh-CN:
base:
working_days_are_missing: "每周必须至少有一天定义为工作日。"
previous_working_day_changes_unprocessed: "先前对工作日配置的更改尚未应用。"
+ hours_per_day_are_missing: "必须定义每天的小时数"
+ days_per_week_are_missing: "必须定义每周的天数"
+ days_per_month_are_missing: "必须定义每月的天数"
+ durations_are_not_positive_numbers: "持续时间必须是正数"
+ hours_per_day_is_out_of_bounds: "每天小时数不能超过24"
+ days_per_week_is_out_of_bounds: "每周天数不能超过7"
+ days_per_month_is_out_of_bounds: "每月天数不能超过31"
+ days_per_week_and_days_per_month_are_inconsistent: "每周天数及每月天数必须保持一致"
time_entry:
attributes:
hours:
@@ -1124,18 +1147,6 @@ zh-CN:
other: "%{count} 小时"
updated: "从 %{old_value} 更改为 %{value}"
logged_for: "已登录"
- meeting_agenda_item:
- duration:
- added: "设为 %{value}"
- added_html: "设为 %{value}"
- removed: "已删除"
- updated: "从 %{old_value} 更改为 %{value}"
- updated_html: "从 %{old_value}改为 %{value}"
- position:
- updated: "重新排序"
- work_package:
- updated: "从 %{old_value} 更改为 %{value}"
- updated_html: "从 %{old_value}改为 %{value}"
filter:
changeset: "更改集"
message: "论坛"
@@ -1314,8 +1325,8 @@ zh-CN:
button_revoke_access: "撤消访问权限"
button_revoke_all: "全部撤销"
button_revoke_only: "仅撤销 %{shared_role_name}"
- button_publish: "Make public"
- button_unpublish: "Make private"
+ button_publish: "设为公开"
+ button_unpublish: "设为私有"
consent:
checkbox_label: 我已注意到并同意上述情况。
failure_message: 同意失败, 无法继续。
@@ -1568,6 +1579,12 @@ zh-CN:
pdf_gantt: "PDF 甘特图"
image:
omitted: "图像未导出。"
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: 时
days: 天
@@ -1621,7 +1638,7 @@ zh-CN:
dates_changed: "日期已更改"
default_attribute_written: "已写入只读属性"
progress_mode_changed_to_status_based: "更新进度计算"
- status_p_complete_changed: "状态%已更改"
+ status_changed: "状态 '%{status_name}'"
system_update: "OpenProject 系统更新:"
cause_descriptions:
work_package_predecessor_changed_times: 根据前置任务 %{link}的更改
@@ -1638,8 +1655,9 @@ zh-CN:
working: "%{date}现在是工作日"
non_working: "%{date}现在是非工作日"
progress_mode_changed_to_status_based: 进度计算模式设置为基于状态
- status_p_complete_changed: >-
- 状态 "%{status_name}"的 %完成值从 %{old_value}% 变为 %{new_value}%
+ status_excluded_from_totals_set_to_false_message: 现在包含在层次结构总计中
+ status_excluded_from_totals_set_to_true_message: 现在不包含在层次结构总计中
+ status_percent_complete_changed: "完成百分比从 %{old_value}% 变为 %{new_value}%"
system_update:
file_links_journal: >
从现在开始,与文件链接(存储在外部存储器中的文件)相关的活动将出现在“活动”选项卡中。以下是与已经存在的链接相关的活动的表示:
@@ -2296,7 +2314,7 @@ zh-CN:
label_workflow: "工作流"
label_workflow_plural: "工作流"
label_workflow_summary: "摘要"
- label_working_days: "工作日"
+ label_working_days_and_hours: "工作日和工作小时"
label_x_closed_work_packages_abbr:
one: "1 个已关闭"
other: "%{count} 个已关闭"
@@ -2674,7 +2692,7 @@ zh-CN:
permission_save_bcf_queries: "保存 BCF 查询"
permission_manage_public_bcf_queries: "管理公开的 BCF 查询"
permission_edit_attribute_help_texts: "编辑属性帮助文本"
- permission_manage_public_project_queries: "Manage public project lists"
+ permission_manage_public_project_queries: "管理公开项目列表"
placeholders:
default: "-"
project:
@@ -2888,6 +2906,9 @@ zh-CN:
setting_cross_project_work_package_relations: "允许跨项目工作包关系"
setting_first_week_of_year: "全年首周包含"
setting_date_format: "日期"
+ setting_days_per_month: "每月天数"
+ setting_days_per_month_explanation: >-
+ 这将以更自然的方式在显示持续时间时定义什么是 "一个月"(例如,如果一个月是20天,60天就是3个月)。
setting_default_language: "默认语言"
setting_default_projects_modules: "新项目的默认启用模块"
setting_default_projects_public: "新项目默认公开"
@@ -2903,6 +2924,12 @@ zh-CN:
setting_feeds_limit: "Feed 内容限制"
setting_file_max_size_displayed: "内联显示的文本文件的最大大小"
setting_host_name: "主机名"
+ setting_hours_per_day: "每天小时数"
+ setting_hours_per_day_explanation: >-
+ 这将以更自然的方式在显示持续时间时定义什么是 "一天"(例如,如果一天是8小时,32小时就是4天)。
+ setting_days_per_week: "每周天数"
+ setting_days_per_week_explanation: >-
+ 这将以更自然的方式在显示持续时间时定义什么是 "一周"(例如,如果一周是5天,15天就是3周)。
setting_invitation_expiration_days: "激活电子邮件将在此时间后过期"
setting_work_package_done_ratio: "进度计算"
setting_work_package_done_ratio_field: "基于工时"
@@ -3342,12 +3369,12 @@ zh-CN:
additional_privileges_project_or_group: "可能有额外的权限(作为项目成员或组成员)"
working_days:
info: >
- 当安排工作包时,未选择的日期将被跳过(不计入天数)。这些日期可以在工作包级别进行覆盖。
+ 在安排工作包时,未选择的日期将被跳过(且不计入天数)。可以在工作包级别覆盖这些选项。
instance_wide_info: >
添加到以下列表的日期被视为非工作日,在安排工作包时将被跳过。
change_button: "更改工作日"
warning: >
- 更改将一周中的哪几天视为工作日或非工作日会影响此实例的所有项目中所有工作包的开始和结束日期。 请注意,只有在您点击“应用更改”按钮后,更改才会应用。
+ 在这种情况下,更改一周中哪些天被视为工作日或非工作日,会影响所有项目中所有工作包的开始和结束日期。
journal_note:
changed: _**工作日**已更改(%{changes})。_
days:
diff --git a/config/locales/crowdin/zh-TW.yml b/config/locales/crowdin/zh-TW.yml
index 4a0c2a309597..8017d73682db 100644
--- a/config/locales/crowdin/zh-TW.yml
+++ b/config/locales/crowdin/zh-TW.yml
@@ -299,6 +299,12 @@ zh-TW:
is_required_blank_slate:
heading: Required in all projects
description: This project attribute is activated in all projects since the "Required in all projects" option is checked. It cannot be deactivated for individual projects.
+ new_project_mapping_form:
+ add_projects: Add projects
+ include_sub_projects: Include sub-projects
+ project_mapping_filter:
+ label: Search project
+ placeholder: Filter by text
types:
no_results_title_text: 目前沒有可用的類型
form:
@@ -441,12 +447,20 @@ zh-TW:
不能更改任何屬性, 但狀態除外。
123 _ 2 _
筆記: 繼承的值 (例如, 來自子項或關係) 仍將適用。
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
按一下以分配或更改此優先順序的顏色。
它可用於突出顯示表中的工作包。
index:
no_results_title_text: 目前沒有工作項目狀態
no_results_content_text: 新增一個狀態
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "白色主題"
light_high_contrast: "高對比白色主題"
@@ -615,6 +629,7 @@ zh-TW:
status:
is_closed: "關閉工作項目"
is_readonly: "設定「工作項目」唯讀"
+ excluded_from_totals: "Exclude from calculation of totals in hierarchy"
journal:
notes: "備註"
member:
@@ -951,6 +966,14 @@ zh-TW:
base:
working_days_are_missing: "At least one day of the week must be defined as a working day."
previous_working_day_changes_unprocessed: "The previous changes to the working days configuration have not been applied yet."
+ hours_per_day_are_missing: "The number of hours per day must be defined."
+ days_per_week_are_missing: "The number of days per week must be defined."
+ days_per_month_are_missing: "The number of days per month must be defined."
+ durations_are_not_positive_numbers: "The durations must be positive numbers."
+ hours_per_day_is_out_of_bounds: "Hours per day can't be more than 24"
+ days_per_week_is_out_of_bounds: "Days per week can't be more than 7"
+ days_per_month_is_out_of_bounds: "Days per month can't be more than 31"
+ days_per_week_and_days_per_month_are_inconsistent: "The number of days per week and the number of days per month must be consistent."
time_entry:
attributes:
hours:
@@ -1127,18 +1150,6 @@ zh-TW:
other: "%{count} hours"
updated: "從 %{old_value} 更改至 %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "從 %{old_value} 更改至 %{value}"
- updated_html: "從 %{old_value} 更改至 %{value}"
- position:
- updated: "重新排列"
- work_package:
- updated: "從 %{old_value} 更改至 %{value}"
- updated_html: "從 %{old_value} 更改至 %{value}"
filter:
changeset: "變更集"
message: "討論區"
@@ -1571,6 +1582,12 @@ zh-TW:
pdf_gantt: "PDF Gantt"
image:
omitted: "影像沒有匯出。"
+ macro:
+ error: "Macro error, %{message}"
+ attribute_not_found: "attribute not found: %{attribute}"
+ model_not_found: "invalid attribute model: %{model}"
+ resource_not_found: "resource not found: %{resource}"
+ rich_text_unsupported: "Rich text embedding currently not supported in export"
units:
hours: 小時
days: 日
@@ -1624,7 +1641,7 @@ zh-TW:
dates_changed: "日期變更"
default_attribute_written: "Read-only attributes written"
progress_mode_changed_to_status_based: "更新計算後的進度"
- status_p_complete_changed: "Status % Complete changed"
+ status_changed: "Status '%{status_name}'"
system_update: "OpenProject 系統更新:"
cause_descriptions:
work_package_predecessor_changed_times: by changes to predecessor %{link}
@@ -1641,8 +1658,9 @@ zh-TW:
working: "%{date} 已是工作日"
non_working: "%{date} 已非工作日"
progress_mode_changed_to_status_based: 自動計算模式設定成「Status-based」
- status_p_complete_changed: >-
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the Activity tab. The following represent activity concerning links that already existed:
@@ -2299,7 +2317,7 @@ zh-TW:
label_workflow: "工作流程"
label_workflow_plural: "工作流程"
label_workflow_summary: "總覽"
- label_working_days: "工作日"
+ label_working_days_and_hours: "Working days and hours"
label_x_closed_work_packages_abbr:
one: "1 已結束"
other: "%{count} 個已結案"
@@ -2896,6 +2914,9 @@ zh-TW:
setting_cross_project_work_package_relations: "允許跨專案的工作項目關聯"
setting_first_week_of_year: "一年的第一週從哪一天開始"
setting_date_format: "日期"
+ setting_days_per_month: "Days per month"
+ setting_days_per_month_explanation: >-
+ This will define what is considered a "month" when displaying duration in a more natural way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "預設語言"
setting_default_projects_modules: "新專案預設啟用的模組"
setting_default_projects_public: "新專案預設為公開"
@@ -2911,6 +2932,12 @@ zh-TW:
setting_feeds_limit: "Feed 內容限制"
setting_file_max_size_displayed: "直接显示文字文件內容的最大檔案容量"
setting_host_name: "主機名稱"
+ setting_hours_per_day: "Hours per day"
+ setting_hours_per_day_explanation: >-
+ This will define what is considered a "day" when displaying duration in a more natural way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "啟動信件在......天後過期"
setting_work_package_done_ratio: "進度計算"
setting_work_package_done_ratio_field: "Work-based"
@@ -3351,12 +3378,12 @@ zh-TW:
additional_privileges_project_or_group: "Might have additional privileges (as project or group member)"
working_days:
info: >
- 安排工作項目時,未選擇的天數將被跳過(並且不包含在天數計數中)。 這些設定可以在工作項目被改寫覆蓋。
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overridden at a work-package level.
instance_wide_info: >
加到下面列表中的日期被視為非工作日,設定工作項目時程時跳過。
change_button: "修改工作日"
warning: >
- 更改一周中的哪幾天被視為工作日或非工作日,可能會影響所有項目中所有工作項目的開始和結束日期。 請注意,只有在按一下「套用設定」按鈕後才會生效。
+ Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 5c221a64da4c..546bfdb71ed5 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -333,6 +333,12 @@ Project attributes and sections are defined in the Note: Inherited values (e.g., from children or relations) will still apply.
+ status_excluded_from_totals_text: |-
+ Check this option to exclude work packages with this status from totals of Work,
+ Remaining work, and % Complete in a hierarchy.
status_color_text: |
Click to assign or change the color of this status.
It is shown in the status button and can be used for highlighting work packages in the table.
index:
no_results_title_text: There are currently no work package statuses.
no_results_content_text: Add a new status
+ headers:
+ is_default: "Default"
+ is_closed: "Closed"
+ is_readonly: "Read-only"
+ excluded_from_totals: "Excluded from totals"
themes:
light: "Light"
@@ -694,6 +708,7 @@ Project attributes and sections are defined in the %{count} hours"
updated: "changed from %{old_value} to %{value}"
logged_for: "Logged for"
- meeting_agenda_item:
- duration:
- added: "set to %{value}"
- added_html: "set to %{value}"
- removed: "removed"
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
- position:
- updated: "reordered"
- work_package:
- updated: "changed from %{old_value} to %{value}"
- updated_html: "changed from %{old_value} to %{value}"
filter:
changeset: "Changesets"
message: "Forums"
@@ -1705,6 +1716,12 @@ Project attributes and sections are defined in the -
- % complete value for status '%{status_name}' changed from %{old_value}% to %{new_value}%
+ status_excluded_from_totals_set_to_false_message: now included in hierarchy totals
+ status_excluded_from_totals_set_to_true_message: now excluded from hierarchy totals
+ status_percent_complete_changed: "% complete changed from %{old_value}% to %{new_value}%"
system_update:
file_links_journal: >
From now on, activity related to file links (files stored in external storages) will appear here in the
@@ -2449,7 +2467,7 @@ Project attributes and sections are defined in the -
+ This will define what is considered a "month" when displaying duration in a more natural
+ way (for example, if a month is 20 days, 60 days would be 3 months.
setting_default_language: "Default language"
setting_default_projects_modules: "Default enabled modules for new projects"
setting_default_projects_public: "New projects are public by default"
@@ -3106,6 +3128,14 @@ Project attributes and sections are defined in the -
+ This will define what is considered a "day" when displaying duration in a more natural
+ way (for example, if a day is 8 hours, 32 hours would be 4 days).
+ setting_days_per_week: "Days per week"
+ setting_days_per_week_explanation: >-
+ This will define what is considered a "week" when displaying duration in a more natural
+ way (for example, if a week is 5 days, 15 days would be 3 weeks).
setting_invitation_expiration_days: "Activation email expires after"
setting_work_package_done_ratio: "Progress calculation"
setting_work_package_done_ratio_field: "Work-based"
@@ -3634,13 +3664,14 @@ Project attributes and sections are defined in the
- Days that are not selected are skipped when scheduling work packages (and not included in the day count). These can be overriden at a work-package level.
+ Days that are not selected are skipped when scheduling work packages (and not included in the day count).
+ These can be overridden at a work-package level.
instance_wide_info: >
Dates added to the list below are considered non-working and skipped when scheduling work packages.
change_button: "Change working days"
warning: >
- Changing which days of the week are considered working days or non-working days can affect the start and finish days of all work packages in all projects in this instance.
- Please note that changes are only applied after you click on the apply changes button.
+ Changing which days of the week are considered working days or non-working days
+ can affect the start and finish days of all work packages in all projects in this instance.
journal_note:
changed: _**Working days** changed (%{changes})._
days:
diff --git a/config/locales/js-en.yml b/config/locales/js-en.yml
index 5423e3217538..bc65a24cc3ac 100644
--- a/config/locales/js-en.yml
+++ b/config/locales/js-en.yml
@@ -303,6 +303,19 @@ en:
Are you sure you want to continue?
+
+ work_packages_settings:
+ warning_progress_calculation_mode_change_from_status_to_field_html: >-
+ Changing progress calculation mode from status-based to work-based will make
+ % Complete a non-editable field whose value is derived from Work
+ and Remaining work. Existing values for % Complete are preserved.
+ If values for Work and Remaining work were not present, they
+ will be required in order to change % Complete.
+ warning_progress_calculation_mode_change_from_field_to_status_html: >-
+ Changing progress calculation mode from work-based to status-based will result
+ in all existing % Complete values to be lost and replaced with values
+ associated with each status. Existing values for Remaining work may
+ also be recalculated to reflect this change. This action is not reversible.
custom_actions:
date:
specific: "on"
@@ -1379,6 +1392,14 @@ en:
group: "The group is now a part of %{project}. Meanwhile you can already plan with that group and assign work packages for instance."
next_button: "Continue"
+ exclusion_info:
+ modal:
+ title: "Status excluded from hierarchy totals"
+ content: >-
+ The status '%{status_name}' has been configured to be excluded from hierarchy
+ totals of Work, Remaining work, and % Complete. The totals do not take
+ this value into account.
+
favorite_projects:
no_results: "You have no favorite projects"
no_results_subtext: "Add one or multiple projects as favorite through their overview or in a project list."
@@ -1441,7 +1462,7 @@ en:
remove: "Remove"
drop_modal:
focus_grab: "This is a focus anchor for modals. Press shift+tab to go back to the modal trigger element."
- Close: "Close"
+ close: "Close modal"
open_project_storage_modal:
waiting_title:
timeout: "Timeout"
diff --git a/config/routes.rb b/config/routes.rb
index 06c8a660b8b4..2c8206aceff0 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -453,7 +453,9 @@
resource :aggregation, controller: "/admin/settings/aggregation_settings", only: %i[show update]
resource :mail_notifications, controller: "/admin/settings/mail_notifications_settings", only: %i[show update]
resource :api, controller: "/admin/settings/api_settings", only: %i[show update]
- resource :work_packages, controller: "/admin/settings/work_packages_settings", only: %i[show update]
+ # It is important to have this named something else than "work_packages".
+ # Otherwise the angular ui-router will also recognize that as a WorkPackage page and apply according classes.
+ resource :work_package_tracking, controller: "/admin/settings/work_packages_settings", only: %i[show update]
resource :projects, controller: "/admin/settings/projects_settings", only: %i[show update]
resource :new_project, controller: "/admin/settings/new_project_settings", only: %i[show update]
resources :project_custom_fields, controller: "/admin/settings/project_custom_fields" do
@@ -464,6 +466,7 @@
put :drop
get :project_mappings
+ post :link
delete :unlink
end
end
@@ -474,7 +477,7 @@
put :drop
end
end
- resource :working_days, controller: "/admin/settings/working_days_settings", only: %i[show update]
+ resource :working_days_and_hours, controller: "/admin/settings/working_days_and_hours_settings", only: %i[show update]
resource :users, controller: "/admin/settings/users_settings", only: %i[show update]
resource :date_format, controller: "/admin/settings/date_format_settings", only: %i[show update]
resource :icalendar, controller: "/admin/settings/icalendar_settings", only: %i[show update]
diff --git a/db/migrate/20230731153909_add_file_link_journals_to_existing_containers.rb b/db/migrate/20230731153909_add_file_link_journals_to_existing_containers.rb
index 50c7d72dbe08..5e3ff87fd18b 100644
--- a/db/migrate/20230731153909_add_file_link_journals_to_existing_containers.rb
+++ b/db/migrate/20230731153909_add_file_link_journals_to_existing_containers.rb
@@ -37,7 +37,7 @@ def up
next unless container.class.journaled?
Journals::CreateService.new(container, system_user)
- .call(cause: Jounal::CausedBySystemUpdate.new(feature: "file_links_journal"))
+ .call(cause: Journal::CausedBySystemUpdate.new(feature: "file_links_journal"))
end
end
diff --git a/db/migrate/20240424093311_add_excluded_from_totals_to_statuses.rb b/db/migrate/20240424093311_add_excluded_from_totals_to_statuses.rb
new file mode 100644
index 000000000000..dd3e6fbb96dd
--- /dev/null
+++ b/db/migrate/20240424093311_add_excluded_from_totals_to_statuses.rb
@@ -0,0 +1,5 @@
+class AddExcludedFromTotalsToStatuses < ActiveRecord::Migration[7.1]
+ def change
+ add_column :statuses, :excluded_from_totals, :boolean, default: false, null: false
+ end
+end
diff --git a/db/migrate/20240522073759_fix_status_excluded_from_totals_changed_journal_cause.rb b/db/migrate/20240522073759_fix_status_excluded_from_totals_changed_journal_cause.rb
new file mode 100644
index 000000000000..15f610b3ee47
--- /dev/null
+++ b/db/migrate/20240522073759_fix_status_excluded_from_totals_changed_journal_cause.rb
@@ -0,0 +1,72 @@
+# Update journal entries from this:
+#
+# {
+# "type" => "status_p_complete_changed",
+# "status_name" => status.name,
+# "status_id" => status.id,
+# "status_p_complete_change" => [20, 40]
+# }
+#
+# to this:
+#
+# {
+# "type" => "status_changed",
+# "status_name" => status.name,
+# "status_id" => status.id,
+# "status_changes" => { "default_done_ratio" => [20, 40] }
+# }
+#
+# structure needed to handle multiple changes in one cause
+class FixStatusExcludedFromTotalsChangedJournalCause < ActiveRecord::Migration[7.1]
+ def up
+ # With Postgres version 16+, it could be written as:
+ # json_object(
+ # 'type': 'status_changed',
+ # 'status_id': cause -> 'status_id',
+ # 'status_name': cause -> 'status_name',
+ # 'status_changes': json_object(
+ # 'default_done_ratio': cause -> 'status_p_complete_change'
+ # )
+ # )
+ execute(<<~SQL.squish)
+ UPDATE journals
+ SET cause = jsonb_set(
+ jsonb_set(
+ cause,
+ '{type}',
+ '"status_changed"'
+ ),
+ '{status_changes}',
+ jsonb_set(
+ '{"default_done_ratio": ""}'::jsonb,
+ '{default_done_ratio}',
+ cause -> 'status_p_complete_change'
+ )
+ ) - 'status_p_complete_change'
+ WHERE cause @> '{"type": "status_p_complete_changed"}';
+ SQL
+ end
+
+ def down
+ # With Postgres version 16+, it could be written as:
+ # json_object(
+ # 'type': 'status_p_complete_changed',
+ # 'status_id': cause -> 'status_id',
+ # 'status_name': cause -> 'status_name',
+ # 'status_p_complete_change': cause #> '{status_changes,default_done_ratio}'
+ # )
+ execute(<<~SQL.squish)
+ UPDATE journals
+ SET cause = jsonb_set(
+ jsonb_set(
+ cause,
+ '{type}',
+ '"status_p_complete_changed"'
+ ),
+ '{status_p_complete_change}',
+ cause #> '{status_changes,default_done_ratio}'
+ ) - 'status_changes'
+ WHERE cause @> '{"type": "status_changed", "status_changes":{"default_done_ratio":[]}}';
+ SQL
+ end
+end
diff --git a/docker/ci/Dockerfile b/docker/ci/Dockerfile
index f49045a6e38e..6dd5cd31787a 100644
--- a/docker/ci/Dockerfile
+++ b/docker/ci/Dockerfile
@@ -3,7 +3,7 @@ ARG RUBY_VERSION
FROM ruby:${RUBY_VERSION}-bookworm
ENV NODE_VERSION="20.9.0"
-ENV BUNDLER_VERSION="2.5.10"
+ENV BUNDLER_VERSION="2.5.11"
ENV DEBIAN_FRONTEND=noninteractive
ENV BUNDLE_WITHOUT="development:production:docker"
diff --git a/docker/dev/backend/Dockerfile b/docker/dev/backend/Dockerfile
index b32ebf0c5f9e..a4a06c642a3a 100644
--- a/docker/dev/backend/Dockerfile
+++ b/docker/dev/backend/Dockerfile
@@ -1,4 +1,4 @@
-FROM ruby:3.3.1-bullseye as develop
+FROM ruby:3.3.2-bullseye as develop
MAINTAINER operations@openproject.com
ARG DEV_UID=1000
@@ -8,7 +8,7 @@ ENV USER=dev
ENV RAILS_ENV=development
ENV NODE_MAJOR=20
-ENV BUNDLER_VERSION "2.5.10"
+ENV BUNDLER_VERSION "2.5.11"
# `--no-log-init` is required as a workaround to avoid disk exhaustion.
#
diff --git a/docker/prod/Dockerfile b/docker/prod/Dockerfile
index 64910dc83d35..771e53748745 100644
--- a/docker/prod/Dockerfile
+++ b/docker/prod/Dockerfile
@@ -1,8 +1,8 @@
-ARG RUBY_VERSION="3.3.1"
+ARG RUBY_VERSION="3.3.2"
FROM ruby:${RUBY_VERSION}-bookworm as base
LABEL maintainer="operations@openproject.com"
-ARG BUNDLER_VERSION="2.5.10"
+ARG BUNDLER_VERSION="2.5.11"
ARG NODE_VERSION="20.9.0"
ARG BIM_SUPPORT=true
ENV DEBIAN_FRONTEND=noninteractive
diff --git a/docs/development/development-environment-osx/README.md b/docs/development/development-environment-osx/README.md
index 47103efbf0ee..c89e5afc7522 100644
--- a/docs/development/development-environment-osx/README.md
+++ b/docs/development/development-environment-osx/README.md
@@ -27,7 +27,7 @@ their homepage.
Use [rbenv](https://github.com/rbenv/rbenv) and [ruby-build](https://github.com/rbenv/ruby-build#readme) to install
Ruby. We always require the latest ruby versions, and you can check which version is required
by [checking the Gemfile](https://github.com/opf/openproject/blob/dev/Gemfile#L31) for the `ruby "~> X.Y"` statement. At
-the time of writing, this version is "3.3.1"
+the time of writing, this version is "3.3.2"
#### Install rbenv and ruby-build
@@ -45,7 +45,7 @@ $ rbenv init
With both installed, we can now install the actual ruby version. You can check available ruby versions
with `rbenv install --list`.
-At the time of this writing, the latest stable version is `3.3.1`, which we also require.
+At the time of this writing, the latest stable version is `3.3.2`, which we also require.
We suggest you install the version we require in the [Gemfile](https://github.com/opf/openproject/blob/dev/Gemfile).
Search for the `ruby '~> X.Y.Z'` line
@@ -53,14 +53,14 @@ and install that version.
```shell
# Install the required version as read from the Gemfile
-rbenv install 3.3.1
+rbenv install 3.3.2
```
This might take a while depending on whether ruby is built from source. After it is complete, you need to tell rbenv to
globally activate this version
```shell
-rbenv global 3.3.1
+rbenv global 3.3.2
```
You also need to install [bundler](https://github.com/bundler/bundler/), the ruby gem bundler.
@@ -134,10 +134,10 @@ You should now have an active ruby and node installation. Verify that it works w
```shell
$ ruby --version
-ruby 3.3.1 (2024-04-23 revision c56cd86388) [arm64-darwin23]
+ruby 3.3.2 (2024-05-30 revision e5a195edf6) [arm64-darwin23]
$ bundler --version
-Bundler version 2.5.10
+Bundler version 2.5.11
node --version
v20.9.0
diff --git a/docs/development/development-environment-ubuntu/README.md b/docs/development/development-environment-ubuntu/README.md
index 7d7b70f135f2..256b6dab4d91 100644
--- a/docs/development/development-environment-ubuntu/README.md
+++ b/docs/development/development-environment-ubuntu/README.md
@@ -41,7 +41,7 @@ sudo apt-get install git curl build-essential zlib1g-dev libyaml-dev libssl-dev
Use [rbenv](https://github.com/rbenv/rbenv) and [ruby-build](https://github.com/rbenv/ruby-build#readme) to install
Ruby. We always require the latest ruby versions, and you can check which version is required
by [checking the Gemfile](https://github.com/opf/openproject/blob/dev/Gemfile#L31) for the `ruby "~> X.Y"` statement. At
-the time of writing, this version is "3.3.1"
+the time of writing, this version is "3.3.2"
#### Install rbenv and ruby-build
@@ -75,7 +75,7 @@ git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
#### Installing ruby
With both installed, we can now install ruby. You can check available ruby versions with `rbenv install --list`.
-At the time of this writing, the latest stable version is `3.3.1` which we also require.
+At the time of this writing, the latest stable version is `3.3.2` which we also require.
We suggest you install the version we require in the [Gemfile](https://github.com/opf/openproject/blob/dev/Gemfile).
Search for the `ruby '~> X.Y.Z'` line
@@ -83,14 +83,14 @@ and install that version.
```shell
# Install the required version as read from the Gemfile
-rbenv install 3.3.1
+rbenv install 3.3.2
```
This might take a while depending on whether ruby is built from source. After it is complete, you need to tell rbenv to
globally activate this version
```shell
-rbenv global 3.3.1
+rbenv global 3.3.2
rbenv rehash
```
@@ -180,10 +180,10 @@ You should now have an active ruby and node installation. Verify that it works w
```shell
ruby --version
-ruby 3.3.1 (2024-04-23 revision c56cd86388) [arm64-darwin23]
+ruby 3.3.2 (2024-05-30 revision e5a195edf6) [arm64-darwin23]
bundler --version
-Bundler version 2.5.10
+Bundler version 2.5.11
node --version
v20.9.0
diff --git a/docs/installation-and-operations/installation/manual/README.md b/docs/installation-and-operations/installation/manual/README.md
index 79a51e75dae8..ad7c1df7f879 100644
--- a/docs/installation-and-operations/installation/manual/README.md
+++ b/docs/installation-and-operations/installation/manual/README.md
@@ -108,16 +108,16 @@ time to finish.
[openproject@host] source ~/.profile
[openproject@host] git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
-[openproject@host] rbenv install 3.3.1
+[openproject@host] rbenv install 3.3.2
[openproject@host] rbenv rehash
-[openproject@host] rbenv global 3.3.1
+[openproject@host] rbenv global 3.3.2
```
To check our Ruby installation we run `ruby --version`. It should output
something very similar to:
```text
-ruby 3.3.1 (2024-04-23 revision c56cd86388) [arm64-darwin23]
+ruby 3.3.2 (2024-05-30 revision e5a195edf6) [arm64-darwin23]
```
## Installation of Node
diff --git a/docs/release-notes/14-1-1/README.md b/docs/release-notes/14-1-1/README.md
new file mode 100644
index 000000000000..94b8c0162bbf
--- /dev/null
+++ b/docs/release-notes/14-1-1/README.md
@@ -0,0 +1,29 @@
+---
+title: OpenProject 14.1.1
+sidebar_navigation:
+ title: 14.1.1
+release_version: 14.1.1
+release_date: 2024-06-04
+---
+
+# OpenProject 14.1.1
+
+Release date: 2024-06-04
+
+We released [OpenProject 14.1.1](https://community.openproject.org/versions/2056).
+The release contains several bug fixes and we recommend updating to the newest version.
+
+
+
+## Bug fixes and changes
+
+
+
+
+- Bugfix: Waiting modal doesn't time out \[[#55016](https://community.openproject.org/wp/55016)\]
+- Bugfix: ScheduleReminderMailsNotificationsJob constantly broken after 24 hour outage - no reminder mails send \[[#55223](https://community.openproject.org/wp/55223)\]
+- Bugfix: The available\_projects api endpoint displays custom project fields incorrectly \[[#55381](https://community.openproject.org/wp/55381)\]
+- Bugfix: Typo in historic migation \[[#55421](https://community.openproject.org/wp/55421)\]
+
+
+
diff --git a/docs/release-notes/README.md b/docs/release-notes/README.md
index 6efe42df3bbb..e458586215a9 100644
--- a/docs/release-notes/README.md
+++ b/docs/release-notes/README.md
@@ -13,6 +13,13 @@ Stay up to date and get an overview of the new features included in the releases
+## 14.1.1
+
+Release date: 2024-06-04
+
+[Release Notes](14-1-1/)
+
+
## 14.1.0
Release date: 2024-05-22
diff --git a/docs/system-admin-guide/integrations/README.md b/docs/system-admin-guide/integrations/README.md
index 5221d4653968..85049af181ac 100644
--- a/docs/system-admin-guide/integrations/README.md
+++ b/docs/system-admin-guide/integrations/README.md
@@ -50,6 +50,13 @@ OpenProject offers an integration with OneDrive/Sharepoint for file storage and
> **Note**: OneDrive/SharePoint integration is an Enterprise add-on and can only be used with [Enterprise cloud](../../enterprise-guide/enterprise-cloud-guide/) or [Enterprise on-premises](../../enterprise-guide/enterprise-on-premises-guide/). An upgrade from the free Community edition is easy and helps support OpenProject.
+
+## SL2OP
+
+SL2OP is an integration between SelectLine ERP and OpenProject. Please note that it was developed and is maintained by DAKO-IT, we do not provide any support for it. You can find more information [here](https://dako-it.com/captain-finn-software-fuer-selectline/schnittstelle-openproject-fuer-selectline/detail/80).
+
+> **Note**: it is currently only available in German.
+
## Slack
There is a rudimentary OpenProject Slack integration from the community. It messages a configured Slack channel, every time a Work Package or Wiki site is modified. This integration is not officially supported by OpenProject.
diff --git a/frontend/.eslintignore b/frontend/.eslintignore
index 1c7abcc8fb96..97b5851b7071 100644
--- a/frontend/.eslintignore
+++ b/frontend/.eslintignore
@@ -1,2 +1,3 @@
.eslintrc.js
-vendor
\ No newline at end of file
+vendor
+src/app/shared/helpers/chronic_duration.js
diff --git a/frontend/.eslintrc.js b/frontend/.eslintrc.js
index 0481eb6edfca..79d2b8796959 100644
--- a/frontend/.eslintrc.js
+++ b/frontend/.eslintrc.js
@@ -25,7 +25,7 @@ module.exports = {
project: "./src/tsconfig.app.json",
tsconfigRootDir: __dirname,
sourceType: "module",
- createDefaultProgram: true
+ createDefaultProgram: true,
},
extends: [
"plugin:@typescript-eslint/recommended",
@@ -49,11 +49,10 @@ module.exports = {
"error",
{"type": "element", "prefix": ["op", "opce"], "style": "kebab-case"},
],
- "@angular-eslint/component-class-suffix": ["error", { "suffixes": ["Component", "Example"] }],
+ "@angular-eslint/component-class-suffix": ["error", {"suffixes": ["Component", "Example"]}],
// Warn when new components are being created without OnPush
"change-detection-strategy/on-push": "error",
-
"no-console": [
"error",
{
@@ -65,8 +64,8 @@ module.exports = {
],
// Sometimes we need to shush the TypeScript compiler
- "no-unused-vars": ["error", { "varsIgnorePattern": "^_", "argsIgnorePattern": "^_" }],
- "@typescript-eslint/no-unused-vars": ["error", { "varsIgnorePattern": "^_", "argsIgnorePattern": "^_" }],
+ "no-unused-vars": ["error", {"varsIgnorePattern": "^_", "argsIgnorePattern": "^_"}],
+ "@typescript-eslint/no-unused-vars": ["error", {"varsIgnorePattern": "^_", "argsIgnorePattern": "^_"}],
// Who cares about line length
"max-len": "off",
@@ -75,11 +74,11 @@ module.exports = {
"object-curly-newline": "off",
// Allow short circuit evaluations
- "@typescript-eslint/no-unused-expressions": ["error", { "allowShortCircuit": true }],
+ "@typescript-eslint/no-unused-expressions": ["error", {"allowShortCircuit": true}],
// Force single quotes to align with ruby
quotes: "off",
- "@typescript-eslint/quotes": ["error", "single", { avoidEscape: true }],
+ "@typescript-eslint/quotes": ["error", "single", {avoidEscape: true}],
// Disable webpack loader definitions
"import/no-webpack-loader-syntax": "off",
@@ -103,14 +102,14 @@ module.exports = {
// No void at all collides with `@typescript-eslint/no-floating-promises` which wants us to handle each promise.
// Until we do that, `void` is a good way to explicitly mark unhandled promises.
- "no-void": ["error", { allowAsStatement: true }],
+ "no-void": ["error", {allowAsStatement: true}],
// Disable no-use for functions and classes
- "no-use-before-define": ["error", { "functions": false, "classes": false }],
- "@typescript-eslint/no-use-before-define": ["error", { "functions": false, "classes": false }],
+ "no-use-before-define": ["error", {"functions": false, "classes": false}],
+ "@typescript-eslint/no-use-before-define": ["error", {"functions": false, "classes": false}],
// Allow subsequent single fields in typescript classes
- "@typescript-eslint/lines-between-class-members": ["error", "always", { "exceptAfterSingleLine": true }],
+ "@typescript-eslint/lines-between-class-members": ["error", "always", {"exceptAfterSingleLine": true}],
// Disable indentation rule as it breaks in edge cases and is covered by editorconfig
"indent": "off",
@@ -162,14 +161,14 @@ module.exports = {
allowAfterThisConstructor: false,
enforceInMethodNames: true,
allowFunctionParams: true,
- }
+ },
],
"no-return-assign": ["error", "except-parens"],
- "no-plusplus": ["error", { "allowForLoopAfterthoughts": true }],
+ "no-plusplus": ["error", {"allowForLoopAfterthoughts": true}],
// https://typescript-eslint.io/rules/no-base-to-string/ Disable false positives due to missing types
- "@typescript-eslint/no-base-to-string": ["error", { "ignoredTypeNames": ["URI", "Error", "RegExp", "URL", "URLSearchParams"] }],
+ "@typescript-eslint/no-base-to-string": ["error", {"ignoredTypeNames": ["URI", "Error", "RegExp", "URL", "URLSearchParams"]}],
//////////////////////////////////////////////////////////////////////
// Anything below this line should be turned on again at some point //
@@ -177,13 +176,12 @@ module.exports = {
// It's common in Angular to wrap even pure functions in classes for injection purposes
"class-methods-use-this": "off",
- }
+ },
},
{
files: ["*.html"],
extends: ["plugin:@angular-eslint/template/recommended"],
- rules: {
- }
+ rules: {},
},
{
files: ["*.spec.ts"],
@@ -200,7 +198,7 @@ module.exports = {
// Allow more than one class definitions per file (test components)
"max-classes-per-file": "off",
- }
- }
+ },
+ },
],
};
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 607f0787cdf1..f368c4bca0cb 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -46,8 +46,8 @@
"@ng-select/ng-select": "^12.0.7",
"@ngneat/content-loader": "^7.0.0",
"@ngx-formly/core": "^6.1.4",
- "@openproject/octicons-angular": "^19.13.0",
- "@openproject/primer-view-components": "^0.32.1",
+ "@openproject/octicons-angular": "^19.14.0",
+ "@openproject/primer-view-components": "^0.33.1",
"@openproject/reactivestates": "^3.0.1",
"@primer/css": "^21.2.2",
"@types/hotwired__turbo": "^8.0.1",
@@ -3352,16 +3352,16 @@
"integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q=="
},
"node_modules/@fullcalendar/angular": {
- "version": "6.1.13",
- "resolved": "https://registry.npmjs.org/@fullcalendar/angular/-/angular-6.1.13.tgz",
- "integrity": "sha512-2JxrIUl6xtAAou3a5i/XmovyWwqTMYBmI+6RhyVcx38EhpyFOMlAtx+63m8m2ADJSiph6Nc9nkKFN/A+rR0F7g==",
+ "version": "6.1.14",
+ "resolved": "https://registry.npmjs.org/@fullcalendar/angular/-/angular-6.1.14.tgz",
+ "integrity": "sha512-No6BFb6/KBjj7CMYy5MYq27Q2ycWqZUIupDExpcm5SuJy8c+SwFSnjGzu0Tm4/i0Z48n+ssQ/wjVVSUQcekbZg==",
"dependencies": {
"tslib": "^2.3.0"
},
"peerDependencies": {
- "@angular/common": "12 - 17",
- "@angular/core": "12 - 17",
- "@fullcalendar/core": "~6.1.13"
+ "@angular/common": "12 - 18",
+ "@angular/core": "12 - 18",
+ "@fullcalendar/core": "~6.1.14"
}
},
"node_modules/@fullcalendar/common": {
@@ -3373,54 +3373,54 @@
}
},
"node_modules/@fullcalendar/core": {
- "version": "6.1.13",
- "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.13.tgz",
- "integrity": "sha512-Cps/hMQan4kwnsBhFf2+m2mijbGoWs6r18ZzxBnAAOkkNHtPmHU8EdR6lF+ZLsiVvb7nsC4H/ZKqnxXWwgpoPw==",
+ "version": "6.1.14",
+ "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.14.tgz",
+ "integrity": "sha512-hIPRBevm0aMc2aHy1hRIJgXmI1QTvQM1neQa9oxtuqUmF1+ApYC3oAdwcQMTuI7lHHw3pKJDyJFkKLPPnL6HXA==",
"dependencies": {
"preact": "~10.12.1"
}
},
"node_modules/@fullcalendar/daygrid": {
- "version": "6.1.13",
- "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.13.tgz",
- "integrity": "sha512-0I0hL1kgGjkZuc7Qt8mu4jjrqIL5PZzd58bEpTxoXRKI5UBZ9KbshGVMryQSXYANlrRtkPnXVt90VIDrxZbDrA==",
+ "version": "6.1.14",
+ "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.14.tgz",
+ "integrity": "sha512-DSyjiA1dEM8k3bOCrZpZOmAOZu71KGtH02ze+4QKuhxkmn/zQghmmLRdfzpOrcyJg6xGKkoB4pBcO+2lXar8XQ==",
"peerDependencies": {
- "@fullcalendar/core": "~6.1.13"
+ "@fullcalendar/core": "~6.1.14"
}
},
"node_modules/@fullcalendar/interaction": {
- "version": "6.1.13",
- "resolved": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-6.1.13.tgz",
- "integrity": "sha512-r1w+jqCRGZZyxKFquueDSFvbsFhJLhc1BX8Nlyz684lYxS1SiToYJW9Q8X/XkySCzpjO3KOnxEp2jVOn1Usyjg==",
+ "version": "6.1.14",
+ "resolved": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-6.1.14.tgz",
+ "integrity": "sha512-rXum5XCjq+WEPNctFeYL/JKZGeU2rlxrElygocdMegcrIBJQW5hnWWVE+i4/1dOmUKF80CbGVlXUyYXoqK2eFg==",
"peerDependencies": {
- "@fullcalendar/core": "~6.1.13"
+ "@fullcalendar/core": "~6.1.14"
}
},
"node_modules/@fullcalendar/list": {
- "version": "6.1.13",
- "resolved": "https://registry.npmjs.org/@fullcalendar/list/-/list-6.1.13.tgz",
- "integrity": "sha512-bPW4EsgGNwDZh91NtD+q4hqGfS6jEvCXQo7+MNy4JLMwFtdenEURRrzsb6CW3l97L3Vp0E2mSqiXaNESOmXEcQ==",
+ "version": "6.1.14",
+ "resolved": "https://registry.npmjs.org/@fullcalendar/list/-/list-6.1.14.tgz",
+ "integrity": "sha512-eV0/6iCumYfvlPzIUTAONWH17/JlQCyCChUz8m06L4E/sOiNjkHGz8vlVTmZKqXzx9oWOOyV/Nm3pCtHmVZh+Q==",
"peerDependencies": {
- "@fullcalendar/core": "~6.1.13"
+ "@fullcalendar/core": "~6.1.14"
}
},
"node_modules/@fullcalendar/premium-common": {
- "version": "6.1.13",
- "resolved": "https://registry.npmjs.org/@fullcalendar/premium-common/-/premium-common-6.1.13.tgz",
- "integrity": "sha512-ym68zNPUYGSROsgh/7hcEfIZ56MLCO4ffqF/MABldwKYN0qOIbWfB+EBfr9I6L1nIb5FNKzwhAlTGh9/y/R/BQ==",
+ "version": "6.1.14",
+ "resolved": "https://registry.npmjs.org/@fullcalendar/premium-common/-/premium-common-6.1.14.tgz",
+ "integrity": "sha512-Fw8GZ6mjZtv6toliSr3iHwIqLIjx3+7fdd828OO4LGzX1wcnCd74CfWqR1tvg+9YLUKmRXNEGgQaN4y5j/XpKg==",
"peerDependencies": {
- "@fullcalendar/core": "~6.1.13"
+ "@fullcalendar/core": "~6.1.14"
}
},
"node_modules/@fullcalendar/resource": {
- "version": "6.1.13",
- "resolved": "https://registry.npmjs.org/@fullcalendar/resource/-/resource-6.1.13.tgz",
- "integrity": "sha512-4s34o4qNbPNY1Zo6EyAXylT1D7uAENcmlvSwWADkzH+Rx0aVyY8wdhCXqzqyTcgYz6jRrD32asRjVyWlXJWD8A==",
+ "version": "6.1.14",
+ "resolved": "https://registry.npmjs.org/@fullcalendar/resource/-/resource-6.1.14.tgz",
+ "integrity": "sha512-iTwFIZ/EMDoUaJArsNXbpIeGjkQLgm1R4lKD7WwJ2bC+FGNwCs3lVDYrWaCwCggt38BoVDewWcSVkDy1lyhd3A==",
"dependencies": {
- "@fullcalendar/premium-common": "~6.1.13"
+ "@fullcalendar/premium-common": "~6.1.14"
},
"peerDependencies": {
- "@fullcalendar/core": "~6.1.13"
+ "@fullcalendar/core": "~6.1.14"
}
},
"node_modules/@fullcalendar/resource-common": {
@@ -3443,51 +3443,51 @@
}
},
"node_modules/@fullcalendar/resource-timeline": {
- "version": "6.1.13",
- "resolved": "https://registry.npmjs.org/@fullcalendar/resource-timeline/-/resource-timeline-6.1.13.tgz",
- "integrity": "sha512-ASCLiiuJIgViaoUGPxdK1eI2gNo8AwXSnuwZUpGYMPlHPgqYhm5PwGKvZX8pZfhWa9FFIHWr5cDEMyv5UwJxfQ==",
+ "version": "6.1.14",
+ "resolved": "https://registry.npmjs.org/@fullcalendar/resource-timeline/-/resource-timeline-6.1.14.tgz",
+ "integrity": "sha512-YzmGlfIRMiXHnHSJXdHiW9rqNEVgMHNlgBi5dDmd/g5huhJeHa+thZsy0rrFbHorN+ZQWX2m0R5DIhpLtnmGog==",
"dependencies": {
- "@fullcalendar/premium-common": "~6.1.13",
- "@fullcalendar/scrollgrid": "~6.1.13",
- "@fullcalendar/timeline": "~6.1.13"
+ "@fullcalendar/premium-common": "~6.1.14",
+ "@fullcalendar/scrollgrid": "~6.1.14",
+ "@fullcalendar/timeline": "~6.1.14"
},
"peerDependencies": {
- "@fullcalendar/core": "~6.1.13",
- "@fullcalendar/resource": "~6.1.13"
+ "@fullcalendar/core": "~6.1.14",
+ "@fullcalendar/resource": "~6.1.14"
}
},
"node_modules/@fullcalendar/scrollgrid": {
- "version": "6.1.13",
- "resolved": "https://registry.npmjs.org/@fullcalendar/scrollgrid/-/scrollgrid-6.1.13.tgz",
- "integrity": "sha512-gIsEGkOfLPMAqclYiZeSyzWxUM+mzlWCFqv1SnJRN6bsO5Lx3hibqWDJDDYgpTFHwjIQKNKGhuxN89lXsi/P9g==",
+ "version": "6.1.14",
+ "resolved": "https://registry.npmjs.org/@fullcalendar/scrollgrid/-/scrollgrid-6.1.14.tgz",
+ "integrity": "sha512-LVLdjMgzf0uDNWzB7GWOrZAGF61pa/J0ipJHfG3BTO5Ri5qZbOHpVcPuW94LOFnaGZpbaOG2YQlKygrujAAbvA==",
"dependencies": {
- "@fullcalendar/premium-common": "~6.1.13"
+ "@fullcalendar/premium-common": "~6.1.14"
},
"peerDependencies": {
- "@fullcalendar/core": "~6.1.13"
+ "@fullcalendar/core": "~6.1.14"
}
},
"node_modules/@fullcalendar/timegrid": {
- "version": "6.1.13",
- "resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-6.1.13.tgz",
- "integrity": "sha512-8Ub2mSV+6Mh8WWDKuyCYbj5PKYpmyjSctpJ/21fDBJduE9QFS0WfG9CZZxSJT7CT+srnyk4mX2/5gYN9gYZjUg==",
+ "version": "6.1.14",
+ "resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-6.1.14.tgz",
+ "integrity": "sha512-ZByc3BVAtxWSVfyaNedROLlg/Tb2NQ43+MZZAfBSrVwVm2xyfQ+Bsx3pJyCXsRsUh2TFFTO07q7nMWe0jet3KQ==",
"dependencies": {
- "@fullcalendar/daygrid": "~6.1.13"
+ "@fullcalendar/daygrid": "~6.1.14"
},
"peerDependencies": {
- "@fullcalendar/core": "~6.1.13"
+ "@fullcalendar/core": "~6.1.14"
}
},
"node_modules/@fullcalendar/timeline": {
- "version": "6.1.13",
- "resolved": "https://registry.npmjs.org/@fullcalendar/timeline/-/timeline-6.1.13.tgz",
- "integrity": "sha512-5lqjZYE1Mu+2xHb1Y9J/E8BlyHsu0FeGzPQoyL3L6rqTwttxv1Dpxy28teWr8KN9NpCGKYQCMFzbADo6DEgHeA==",
+ "version": "6.1.14",
+ "resolved": "https://registry.npmjs.org/@fullcalendar/timeline/-/timeline-6.1.14.tgz",
+ "integrity": "sha512-5UvugmoJsXeinrHwH57hMgFWh77KagWtxOkrSL5DwaRj4DTb2loV/pkYD5GJaMjpsZqZcUW0V8kICUzNbkZXag==",
"dependencies": {
- "@fullcalendar/premium-common": "~6.1.13",
- "@fullcalendar/scrollgrid": "~6.1.13"
+ "@fullcalendar/premium-common": "~6.1.14",
+ "@fullcalendar/scrollgrid": "~6.1.14"
},
"peerDependencies": {
- "@fullcalendar/core": "~6.1.13"
+ "@fullcalendar/core": "~6.1.14"
}
},
"node_modules/@github/auto-check-element": {
@@ -4079,9 +4079,9 @@
}
},
"node_modules/@ngx-formly/core": {
- "version": "6.3.2",
- "resolved": "https://registry.npmjs.org/@ngx-formly/core/-/core-6.3.2.tgz",
- "integrity": "sha512-rPnPDkZp+ns6FxpFBGOJLw3p2JYbIZlM+azNlsmDly4E/WlzX4YOPJNh87nNBINH4OqU99yLURkJFIcGGa9Qcg==",
+ "version": "6.3.3",
+ "resolved": "https://registry.npmjs.org/@ngx-formly/core/-/core-6.3.3.tgz",
+ "integrity": "sha512-Dlbxzxrq5J9oNghwJnljtt/rvIeyfqwPQcCkLfsIc04yyztHl8M5cfkQtqqj2VjyEOqQb/XGjt0eQhAXz3xnNg==",
"dependencies": {
"tslib": "^2.0.0"
},
@@ -4802,9 +4802,9 @@
"integrity": "sha512-jrqoTI8lk5UziDsDPJ2Y+nmXYCcRhmr6uMARr3v/W6AMxRgsnRLWJyWKYr6FjaGMgbyxXG+OkCUPQY4Xl3toGg=="
},
"node_modules/@openproject/octicons-angular": {
- "version": "19.13.0",
- "resolved": "https://registry.npmjs.org/@openproject/octicons-angular/-/octicons-angular-19.13.0.tgz",
- "integrity": "sha512-rpqWRFDmtp7N1Baxf4q3hIOAKlzzx0xqMFd3sgpCblJjioOdtDGJlu6coFEEK4bZaQ5AMJdj7iUA0R3F5pQjpA==",
+ "version": "19.14.0",
+ "resolved": "https://registry.npmjs.org/@openproject/octicons-angular/-/octicons-angular-19.14.0.tgz",
+ "integrity": "sha512-26r+Fq5f8ZhWfwH3JwK18eOgK3juzNf9dIidVRRmjFXxTY6oreozclCQf1lqZMlxi3gVUTj9qB35hwINWtMPJQ==",
"dependencies": {
"tslib": "^2.3.0"
},
@@ -4816,9 +4816,9 @@
}
},
"node_modules/@openproject/primer-view-components": {
- "version": "0.32.1",
- "resolved": "https://registry.npmjs.org/@openproject/primer-view-components/-/primer-view-components-0.32.1.tgz",
- "integrity": "sha512-kaw88/hzmciaac4m4wHfcgGL7hTkus3ihz77hByuQXvKXmVvfuJ0uJS129JPc7dUXaWeUK2R6jshWHPG2z+xFw==",
+ "version": "0.33.1",
+ "resolved": "https://registry.npmjs.org/@openproject/primer-view-components/-/primer-view-components-0.33.1.tgz",
+ "integrity": "sha512-lOKqObPWYfuscBJnj0fFuyq8Lz/sQYBlXsvFAs3N1Nu0XSDH/Ak97bFcuIIX4lRWxnyGWSj/BREvIjCoyi2BCA==",
"dependencies": {
"@github/auto-check-element": "^5.2.0",
"@github/auto-complete-element": "^3.6.2",
@@ -4883,9 +4883,9 @@
},
"node_modules/@primer/view-components": {
"name": "@openproject/primer-view-components",
- "version": "0.32.1",
- "resolved": "https://registry.npmjs.org/@openproject/primer-view-components/-/primer-view-components-0.32.1.tgz",
- "integrity": "sha512-kaw88/hzmciaac4m4wHfcgGL7hTkus3ihz77hByuQXvKXmVvfuJ0uJS129JPc7dUXaWeUK2R6jshWHPG2z+xFw==",
+ "version": "0.33.1",
+ "resolved": "https://registry.npmjs.org/@openproject/primer-view-components/-/primer-view-components-0.33.1.tgz",
+ "integrity": "sha512-lOKqObPWYfuscBJnj0fFuyq8Lz/sQYBlXsvFAs3N1Nu0XSDH/Ak97bFcuIIX4lRWxnyGWSj/BREvIjCoyi2BCA==",
"dependencies": {
"@github/auto-check-element": "^5.2.0",
"@github/auto-complete-element": "^3.6.2",
@@ -5719,16 +5719,16 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.11.0.tgz",
- "integrity": "sha512-P+qEahbgeHW4JQ/87FuItjBj8O3MYv5gELDzr8QaQ7fsll1gSMTYb6j87MYyxwf3DtD7uGFB9ShwgmCJB5KmaQ==",
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.12.0.tgz",
+ "integrity": "sha512-7F91fcbuDf/d3S8o21+r3ZncGIke/+eWk0EpO21LXhDfLahriZF9CGj4fbAetEjlaBdjdSm9a6VeXbpbT6Z40Q==",
"dev": true,
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
- "@typescript-eslint/scope-manager": "7.11.0",
- "@typescript-eslint/type-utils": "7.11.0",
- "@typescript-eslint/utils": "7.11.0",
- "@typescript-eslint/visitor-keys": "7.11.0",
+ "@typescript-eslint/scope-manager": "7.12.0",
+ "@typescript-eslint/type-utils": "7.12.0",
+ "@typescript-eslint/utils": "7.12.0",
+ "@typescript-eslint/visitor-keys": "7.12.0",
"graphemer": "^1.4.0",
"ignore": "^5.3.1",
"natural-compare": "^1.4.0",
@@ -5752,13 +5752,13 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.11.0.tgz",
- "integrity": "sha512-27tGdVEiutD4POirLZX4YzT180vevUURJl4wJGmm6TrQoiYwuxTIY98PBp6L2oN+JQxzE0URvYlzJaBHIekXAw==",
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.12.0.tgz",
+ "integrity": "sha512-itF1pTnN6F3unPak+kutH9raIkL3lhH1YRPGgt7QQOh43DQKVJXmWkpb+vpc/TiDHs6RSd9CTbDsc/Y+Ygq7kg==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "7.11.0",
- "@typescript-eslint/visitor-keys": "7.11.0"
+ "@typescript-eslint/types": "7.12.0",
+ "@typescript-eslint/visitor-keys": "7.12.0"
},
"engines": {
"node": "^18.18.0 || >=20.0.0"
@@ -5768,26 +5768,103 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": {
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.12.0.tgz",
+ "integrity": "sha512-lib96tyRtMhLxwauDWUp/uW3FMhLA6D0rJ8T7HmH7x23Gk1Gwwu8UZ94NMXBvOELn6flSPiBrCKlehkiXyaqwA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "7.12.0",
+ "@typescript-eslint/utils": "7.12.0",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.56.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.11.0.tgz",
- "integrity": "sha512-MPEsDRZTyCiXkD4vd3zywDCifi7tatc4K37KqTprCvaXptP7Xlpdw0NR2hRJTetG5TxbWDB79Ys4kLmHliEo/w==",
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.12.0.tgz",
+ "integrity": "sha512-o+0Te6eWp2ppKY3mLCU+YA9pVJxhUJE15FV7kxuD9jgwIAa+w/ycGJBMrYDTpVGUM/tgpa9SeMOugSabWFq7bg==",
+ "dev": true,
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": {
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.12.0.tgz",
+ "integrity": "sha512-5bwqLsWBULv1h6pn7cMW5dXX/Y2amRqLaKqsASVwbBHMZSnHqE/HN4vT4fE0aFsiwxYvr98kqOWh1a8ZKXalCQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "7.12.0",
+ "@typescript-eslint/visitor-keys": "7.12.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "^9.0.4",
+ "semver": "^7.6.0",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": {
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.12.0.tgz",
+ "integrity": "sha512-Y6hhwxwDx41HNpjuYswYp6gDbkiZ8Hin9Bf5aJQn1bpTs3afYY4GX+MPYxma8jtoIV2GRwTM/UJm/2uGCVv+DQ==",
"dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@typescript-eslint/scope-manager": "7.12.0",
+ "@typescript-eslint/types": "7.12.0",
+ "@typescript-eslint/typescript-estree": "7.12.0"
+ },
"engines": {
"node": "^18.18.0 || >=20.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.56.0"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.11.0.tgz",
- "integrity": "sha512-7syYk4MzjxTEk0g/w3iqtgxnFQspDJfn6QKD36xMuuhTzjcxY7F8EmBLnALjVyaOF1/bVocu3bS/2/F7rXrveQ==",
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.12.0.tgz",
+ "integrity": "sha512-uZk7DevrQLL3vSnfFl5bj4sL75qC9D6EdjemIdbtkuUmIheWpuiiylSY01JxJE7+zGrOWDZrp1WxOuDntvKrHQ==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "7.11.0",
+ "@typescript-eslint/types": "7.12.0",
"eslint-visitor-keys": "^3.4.3"
},
"engines": {
@@ -5798,16 +5875,40 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/minimatch": {
+ "version": "9.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz",
+ "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/@typescript-eslint/parser": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.11.0.tgz",
- "integrity": "sha512-yimw99teuaXVWsBcPO1Ais02kwJ1jmNA1KxE7ng0aT7ndr1pT1wqj0OJnsYVGKKlc4QJai86l/025L6z8CljOg==",
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.12.0.tgz",
+ "integrity": "sha512-dm/J2UDY3oV3TKius2OUZIFHsomQmpHtsV0FTh1WO8EKgHLQ1QCADUqscPgTpU+ih1e21FQSRjXckHn3txn6kQ==",
"dev": true,
"dependencies": {
- "@typescript-eslint/scope-manager": "7.11.0",
- "@typescript-eslint/types": "7.11.0",
- "@typescript-eslint/typescript-estree": "7.11.0",
- "@typescript-eslint/visitor-keys": "7.11.0",
+ "@typescript-eslint/scope-manager": "7.12.0",
+ "@typescript-eslint/types": "7.12.0",
+ "@typescript-eslint/typescript-estree": "7.12.0",
+ "@typescript-eslint/visitor-keys": "7.12.0",
"debug": "^4.3.4"
},
"engines": {
@@ -5827,13 +5928,13 @@
}
},
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.11.0.tgz",
- "integrity": "sha512-27tGdVEiutD4POirLZX4YzT180vevUURJl4wJGmm6TrQoiYwuxTIY98PBp6L2oN+JQxzE0URvYlzJaBHIekXAw==",
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.12.0.tgz",
+ "integrity": "sha512-itF1pTnN6F3unPak+kutH9raIkL3lhH1YRPGgt7QQOh43DQKVJXmWkpb+vpc/TiDHs6RSd9CTbDsc/Y+Ygq7kg==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "7.11.0",
- "@typescript-eslint/visitor-keys": "7.11.0"
+ "@typescript-eslint/types": "7.12.0",
+ "@typescript-eslint/visitor-keys": "7.12.0"
},
"engines": {
"node": "^18.18.0 || >=20.0.0"
@@ -5844,9 +5945,9 @@
}
},
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.11.0.tgz",
- "integrity": "sha512-MPEsDRZTyCiXkD4vd3zywDCifi7tatc4K37KqTprCvaXptP7Xlpdw0NR2hRJTetG5TxbWDB79Ys4kLmHliEo/w==",
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.12.0.tgz",
+ "integrity": "sha512-o+0Te6eWp2ppKY3mLCU+YA9pVJxhUJE15FV7kxuD9jgwIAa+w/ycGJBMrYDTpVGUM/tgpa9SeMOugSabWFq7bg==",
"dev": true,
"engines": {
"node": "^18.18.0 || >=20.0.0"
@@ -5857,13 +5958,13 @@
}
},
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.11.0.tgz",
- "integrity": "sha512-cxkhZ2C/iyi3/6U9EPc5y+a6csqHItndvN/CzbNXTNrsC3/ASoYQZEt9uMaEp+xFNjasqQyszp5TumAVKKvJeQ==",
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.12.0.tgz",
+ "integrity": "sha512-5bwqLsWBULv1h6pn7cMW5dXX/Y2amRqLaKqsASVwbBHMZSnHqE/HN4vT4fE0aFsiwxYvr98kqOWh1a8ZKXalCQ==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "7.11.0",
- "@typescript-eslint/visitor-keys": "7.11.0",
+ "@typescript-eslint/types": "7.12.0",
+ "@typescript-eslint/visitor-keys": "7.12.0",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
@@ -5885,12 +5986,12 @@
}
},
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.11.0.tgz",
- "integrity": "sha512-7syYk4MzjxTEk0g/w3iqtgxnFQspDJfn6QKD36xMuuhTzjcxY7F8EmBLnALjVyaOF1/bVocu3bS/2/F7rXrveQ==",
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.12.0.tgz",
+ "integrity": "sha512-uZk7DevrQLL3vSnfFl5bj4sL75qC9D6EdjemIdbtkuUmIheWpuiiylSY01JxJE7+zGrOWDZrp1WxOuDntvKrHQ==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "7.11.0",
+ "@typescript-eslint/types": "7.12.0",
"eslint-visitor-keys": "^3.4.3"
},
"engines": {
@@ -24698,9 +24799,9 @@
"integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q=="
},
"@fullcalendar/angular": {
- "version": "6.1.13",
- "resolved": "https://registry.npmjs.org/@fullcalendar/angular/-/angular-6.1.13.tgz",
- "integrity": "sha512-2JxrIUl6xtAAou3a5i/XmovyWwqTMYBmI+6RhyVcx38EhpyFOMlAtx+63m8m2ADJSiph6Nc9nkKFN/A+rR0F7g==",
+ "version": "6.1.14",
+ "resolved": "https://registry.npmjs.org/@fullcalendar/angular/-/angular-6.1.14.tgz",
+ "integrity": "sha512-No6BFb6/KBjj7CMYy5MYq27Q2ycWqZUIupDExpcm5SuJy8c+SwFSnjGzu0Tm4/i0Z48n+ssQ/wjVVSUQcekbZg==",
"requires": {
"tslib": "^2.3.0"
}
@@ -24714,39 +24815,39 @@
}
},
"@fullcalendar/core": {
- "version": "6.1.13",
- "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.13.tgz",
- "integrity": "sha512-Cps/hMQan4kwnsBhFf2+m2mijbGoWs6r18ZzxBnAAOkkNHtPmHU8EdR6lF+ZLsiVvb7nsC4H/ZKqnxXWwgpoPw==",
+ "version": "6.1.14",
+ "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.14.tgz",
+ "integrity": "sha512-hIPRBevm0aMc2aHy1hRIJgXmI1QTvQM1neQa9oxtuqUmF1+ApYC3oAdwcQMTuI7lHHw3pKJDyJFkKLPPnL6HXA==",
"requires": {
"preact": "~10.12.1"
}
},
"@fullcalendar/daygrid": {
- "version": "6.1.13",
- "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.13.tgz",
- "integrity": "sha512-0I0hL1kgGjkZuc7Qt8mu4jjrqIL5PZzd58bEpTxoXRKI5UBZ9KbshGVMryQSXYANlrRtkPnXVt90VIDrxZbDrA=="
+ "version": "6.1.14",
+ "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.14.tgz",
+ "integrity": "sha512-DSyjiA1dEM8k3bOCrZpZOmAOZu71KGtH02ze+4QKuhxkmn/zQghmmLRdfzpOrcyJg6xGKkoB4pBcO+2lXar8XQ=="
},
"@fullcalendar/interaction": {
- "version": "6.1.13",
- "resolved": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-6.1.13.tgz",
- "integrity": "sha512-r1w+jqCRGZZyxKFquueDSFvbsFhJLhc1BX8Nlyz684lYxS1SiToYJW9Q8X/XkySCzpjO3KOnxEp2jVOn1Usyjg=="
+ "version": "6.1.14",
+ "resolved": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-6.1.14.tgz",
+ "integrity": "sha512-rXum5XCjq+WEPNctFeYL/JKZGeU2rlxrElygocdMegcrIBJQW5hnWWVE+i4/1dOmUKF80CbGVlXUyYXoqK2eFg=="
},
"@fullcalendar/list": {
- "version": "6.1.13",
- "resolved": "https://registry.npmjs.org/@fullcalendar/list/-/list-6.1.13.tgz",
- "integrity": "sha512-bPW4EsgGNwDZh91NtD+q4hqGfS6jEvCXQo7+MNy4JLMwFtdenEURRrzsb6CW3l97L3Vp0E2mSqiXaNESOmXEcQ=="
+ "version": "6.1.14",
+ "resolved": "https://registry.npmjs.org/@fullcalendar/list/-/list-6.1.14.tgz",
+ "integrity": "sha512-eV0/6iCumYfvlPzIUTAONWH17/JlQCyCChUz8m06L4E/sOiNjkHGz8vlVTmZKqXzx9oWOOyV/Nm3pCtHmVZh+Q=="
},
"@fullcalendar/premium-common": {
- "version": "6.1.13",
- "resolved": "https://registry.npmjs.org/@fullcalendar/premium-common/-/premium-common-6.1.13.tgz",
- "integrity": "sha512-ym68zNPUYGSROsgh/7hcEfIZ56MLCO4ffqF/MABldwKYN0qOIbWfB+EBfr9I6L1nIb5FNKzwhAlTGh9/y/R/BQ=="
+ "version": "6.1.14",
+ "resolved": "https://registry.npmjs.org/@fullcalendar/premium-common/-/premium-common-6.1.14.tgz",
+ "integrity": "sha512-Fw8GZ6mjZtv6toliSr3iHwIqLIjx3+7fdd828OO4LGzX1wcnCd74CfWqR1tvg+9YLUKmRXNEGgQaN4y5j/XpKg=="
},
"@fullcalendar/resource": {
- "version": "6.1.13",
- "resolved": "https://registry.npmjs.org/@fullcalendar/resource/-/resource-6.1.13.tgz",
- "integrity": "sha512-4s34o4qNbPNY1Zo6EyAXylT1D7uAENcmlvSwWADkzH+Rx0aVyY8wdhCXqzqyTcgYz6jRrD32asRjVyWlXJWD8A==",
+ "version": "6.1.14",
+ "resolved": "https://registry.npmjs.org/@fullcalendar/resource/-/resource-6.1.14.tgz",
+ "integrity": "sha512-iTwFIZ/EMDoUaJArsNXbpIeGjkQLgm1R4lKD7WwJ2bC+FGNwCs3lVDYrWaCwCggt38BoVDewWcSVkDy1lyhd3A==",
"requires": {
- "@fullcalendar/premium-common": "~6.1.13"
+ "@fullcalendar/premium-common": "~6.1.14"
}
},
"@fullcalendar/resource-common": {
@@ -24771,38 +24872,38 @@
}
},
"@fullcalendar/resource-timeline": {
- "version": "6.1.13",
- "resolved": "https://registry.npmjs.org/@fullcalendar/resource-timeline/-/resource-timeline-6.1.13.tgz",
- "integrity": "sha512-ASCLiiuJIgViaoUGPxdK1eI2gNo8AwXSnuwZUpGYMPlHPgqYhm5PwGKvZX8pZfhWa9FFIHWr5cDEMyv5UwJxfQ==",
+ "version": "6.1.14",
+ "resolved": "https://registry.npmjs.org/@fullcalendar/resource-timeline/-/resource-timeline-6.1.14.tgz",
+ "integrity": "sha512-YzmGlfIRMiXHnHSJXdHiW9rqNEVgMHNlgBi5dDmd/g5huhJeHa+thZsy0rrFbHorN+ZQWX2m0R5DIhpLtnmGog==",
"requires": {
- "@fullcalendar/premium-common": "~6.1.13",
- "@fullcalendar/scrollgrid": "~6.1.13",
- "@fullcalendar/timeline": "~6.1.13"
+ "@fullcalendar/premium-common": "~6.1.14",
+ "@fullcalendar/scrollgrid": "~6.1.14",
+ "@fullcalendar/timeline": "~6.1.14"
}
},
"@fullcalendar/scrollgrid": {
- "version": "6.1.13",
- "resolved": "https://registry.npmjs.org/@fullcalendar/scrollgrid/-/scrollgrid-6.1.13.tgz",
- "integrity": "sha512-gIsEGkOfLPMAqclYiZeSyzWxUM+mzlWCFqv1SnJRN6bsO5Lx3hibqWDJDDYgpTFHwjIQKNKGhuxN89lXsi/P9g==",
+ "version": "6.1.14",
+ "resolved": "https://registry.npmjs.org/@fullcalendar/scrollgrid/-/scrollgrid-6.1.14.tgz",
+ "integrity": "sha512-LVLdjMgzf0uDNWzB7GWOrZAGF61pa/J0ipJHfG3BTO5Ri5qZbOHpVcPuW94LOFnaGZpbaOG2YQlKygrujAAbvA==",
"requires": {
- "@fullcalendar/premium-common": "~6.1.13"
+ "@fullcalendar/premium-common": "~6.1.14"
}
},
"@fullcalendar/timegrid": {
- "version": "6.1.13",
- "resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-6.1.13.tgz",
- "integrity": "sha512-8Ub2mSV+6Mh8WWDKuyCYbj5PKYpmyjSctpJ/21fDBJduE9QFS0WfG9CZZxSJT7CT+srnyk4mX2/5gYN9gYZjUg==",
+ "version": "6.1.14",
+ "resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-6.1.14.tgz",
+ "integrity": "sha512-ZByc3BVAtxWSVfyaNedROLlg/Tb2NQ43+MZZAfBSrVwVm2xyfQ+Bsx3pJyCXsRsUh2TFFTO07q7nMWe0jet3KQ==",
"requires": {
- "@fullcalendar/daygrid": "~6.1.13"
+ "@fullcalendar/daygrid": "~6.1.14"
}
},
"@fullcalendar/timeline": {
- "version": "6.1.13",
- "resolved": "https://registry.npmjs.org/@fullcalendar/timeline/-/timeline-6.1.13.tgz",
- "integrity": "sha512-5lqjZYE1Mu+2xHb1Y9J/E8BlyHsu0FeGzPQoyL3L6rqTwttxv1Dpxy28teWr8KN9NpCGKYQCMFzbADo6DEgHeA==",
+ "version": "6.1.14",
+ "resolved": "https://registry.npmjs.org/@fullcalendar/timeline/-/timeline-6.1.14.tgz",
+ "integrity": "sha512-5UvugmoJsXeinrHwH57hMgFWh77KagWtxOkrSL5DwaRj4DTb2loV/pkYD5GJaMjpsZqZcUW0V8kICUzNbkZXag==",
"requires": {
- "@fullcalendar/premium-common": "~6.1.13",
- "@fullcalendar/scrollgrid": "~6.1.13"
+ "@fullcalendar/premium-common": "~6.1.14",
+ "@fullcalendar/scrollgrid": "~6.1.14"
}
},
"@github/auto-check-element": {
@@ -25275,9 +25376,9 @@
"integrity": "sha512-CjSVVa/9fzMpEDQP01SC4colKCbZwj7vUq0H2bivp8jVsmd21x9Fu0gDBH0Y9NdfAIm4eGZvmiZKMII3vIOaYQ=="
},
"@ngx-formly/core": {
- "version": "6.3.2",
- "resolved": "https://registry.npmjs.org/@ngx-formly/core/-/core-6.3.2.tgz",
- "integrity": "sha512-rPnPDkZp+ns6FxpFBGOJLw3p2JYbIZlM+azNlsmDly4E/WlzX4YOPJNh87nNBINH4OqU99yLURkJFIcGGa9Qcg==",
+ "version": "6.3.3",
+ "resolved": "https://registry.npmjs.org/@ngx-formly/core/-/core-6.3.3.tgz",
+ "integrity": "sha512-Dlbxzxrq5J9oNghwJnljtt/rvIeyfqwPQcCkLfsIc04yyztHl8M5cfkQtqqj2VjyEOqQb/XGjt0eQhAXz3xnNg==",
"requires": {
"tslib": "^2.0.0"
}
@@ -25755,17 +25856,17 @@
"integrity": "sha512-jrqoTI8lk5UziDsDPJ2Y+nmXYCcRhmr6uMARr3v/W6AMxRgsnRLWJyWKYr6FjaGMgbyxXG+OkCUPQY4Xl3toGg=="
},
"@openproject/octicons-angular": {
- "version": "19.13.0",
- "resolved": "https://registry.npmjs.org/@openproject/octicons-angular/-/octicons-angular-19.13.0.tgz",
- "integrity": "sha512-rpqWRFDmtp7N1Baxf4q3hIOAKlzzx0xqMFd3sgpCblJjioOdtDGJlu6coFEEK4bZaQ5AMJdj7iUA0R3F5pQjpA==",
+ "version": "19.14.0",
+ "resolved": "https://registry.npmjs.org/@openproject/octicons-angular/-/octicons-angular-19.14.0.tgz",
+ "integrity": "sha512-26r+Fq5f8ZhWfwH3JwK18eOgK3juzNf9dIidVRRmjFXxTY6oreozclCQf1lqZMlxi3gVUTj9qB35hwINWtMPJQ==",
"requires": {
"tslib": "^2.3.0"
}
},
"@openproject/primer-view-components": {
- "version": "0.32.1",
- "resolved": "https://registry.npmjs.org/@openproject/primer-view-components/-/primer-view-components-0.32.1.tgz",
- "integrity": "sha512-kaw88/hzmciaac4m4wHfcgGL7hTkus3ihz77hByuQXvKXmVvfuJ0uJS129JPc7dUXaWeUK2R6jshWHPG2z+xFw==",
+ "version": "0.33.1",
+ "resolved": "https://registry.npmjs.org/@openproject/primer-view-components/-/primer-view-components-0.33.1.tgz",
+ "integrity": "sha512-lOKqObPWYfuscBJnj0fFuyq8Lz/sQYBlXsvFAs3N1Nu0XSDH/Ak97bFcuIIX4lRWxnyGWSj/BREvIjCoyi2BCA==",
"requires": {
"@github/auto-check-element": "^5.2.0",
"@github/auto-complete-element": "^3.6.2",
@@ -25811,7 +25912,7 @@
"integrity": "sha512-vQoTeu7yfL/1Njg372lN6xqIsiPl0QgoIrkDjJ+TpDkeIznXFc+jLdu+5VUVi+bzyKHwv/gd42hhlLA2K5oD6w==",
"requires": {
"@primer/primitives": "^7.15.12",
- "@primer/view-components": "npm:@openproject/primer-view-components@^0.32.1"
+ "@primer/view-components": "npm:@openproject/primer-view-components@^0.33.1"
}
},
"@primer/primitives": {
@@ -25820,9 +25921,9 @@
"integrity": "sha512-ujAsbRB5Xw6rrxizbTgv1bxpraZ091stPMsO6pqGxzc+zIyhrojpGVBuCKJ+RYkpbKK7T4bZzgOT/KyWBAFwwg=="
},
"@primer/view-components": {
- "version": "npm:@openproject/primer-view-components@0.32.1",
- "resolved": "https://registry.npmjs.org/@openproject/primer-view-components/-/primer-view-components-0.32.1.tgz",
- "integrity": "sha512-kaw88/hzmciaac4m4wHfcgGL7hTkus3ihz77hByuQXvKXmVvfuJ0uJS129JPc7dUXaWeUK2R6jshWHPG2z+xFw==",
+ "version": "npm:@openproject/primer-view-components@0.33.1",
+ "resolved": "https://registry.npmjs.org/@openproject/primer-view-components/-/primer-view-components-0.33.1.tgz",
+ "integrity": "sha512-lOKqObPWYfuscBJnj0fFuyq8Lz/sQYBlXsvFAs3N1Nu0XSDH/Ak97bFcuIIX4lRWxnyGWSj/BREvIjCoyi2BCA==",
"requires": {
"@github/auto-check-element": "^5.2.0",
"@github/auto-complete-element": "^3.6.2",
@@ -26498,16 +26599,16 @@
}
},
"@typescript-eslint/eslint-plugin": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.11.0.tgz",
- "integrity": "sha512-P+qEahbgeHW4JQ/87FuItjBj8O3MYv5gELDzr8QaQ7fsll1gSMTYb6j87MYyxwf3DtD7uGFB9ShwgmCJB5KmaQ==",
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.12.0.tgz",
+ "integrity": "sha512-7F91fcbuDf/d3S8o21+r3ZncGIke/+eWk0EpO21LXhDfLahriZF9CGj4fbAetEjlaBdjdSm9a6VeXbpbT6Z40Q==",
"dev": true,
"requires": {
"@eslint-community/regexpp": "^4.10.0",
- "@typescript-eslint/scope-manager": "7.11.0",
- "@typescript-eslint/type-utils": "7.11.0",
- "@typescript-eslint/utils": "7.11.0",
- "@typescript-eslint/visitor-keys": "7.11.0",
+ "@typescript-eslint/scope-manager": "7.12.0",
+ "@typescript-eslint/type-utils": "7.12.0",
+ "@typescript-eslint/utils": "7.12.0",
+ "@typescript-eslint/visitor-keys": "7.12.0",
"graphemer": "^1.4.0",
"ignore": "^5.3.1",
"natural-compare": "^1.4.0",
@@ -26515,70 +26616,128 @@
},
"dependencies": {
"@typescript-eslint/scope-manager": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.11.0.tgz",
- "integrity": "sha512-27tGdVEiutD4POirLZX4YzT180vevUURJl4wJGmm6TrQoiYwuxTIY98PBp6L2oN+JQxzE0URvYlzJaBHIekXAw==",
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.12.0.tgz",
+ "integrity": "sha512-itF1pTnN6F3unPak+kutH9raIkL3lhH1YRPGgt7QQOh43DQKVJXmWkpb+vpc/TiDHs6RSd9CTbDsc/Y+Ygq7kg==",
"dev": true,
"requires": {
- "@typescript-eslint/types": "7.11.0",
- "@typescript-eslint/visitor-keys": "7.11.0"
+ "@typescript-eslint/types": "7.12.0",
+ "@typescript-eslint/visitor-keys": "7.12.0"
+ }
+ },
+ "@typescript-eslint/type-utils": {
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.12.0.tgz",
+ "integrity": "sha512-lib96tyRtMhLxwauDWUp/uW3FMhLA6D0rJ8T7HmH7x23Gk1Gwwu8UZ94NMXBvOELn6flSPiBrCKlehkiXyaqwA==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/typescript-estree": "7.12.0",
+ "@typescript-eslint/utils": "7.12.0",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^1.3.0"
}
},
"@typescript-eslint/types": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.11.0.tgz",
- "integrity": "sha512-MPEsDRZTyCiXkD4vd3zywDCifi7tatc4K37KqTprCvaXptP7Xlpdw0NR2hRJTetG5TxbWDB79Ys4kLmHliEo/w==",
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.12.0.tgz",
+ "integrity": "sha512-o+0Te6eWp2ppKY3mLCU+YA9pVJxhUJE15FV7kxuD9jgwIAa+w/ycGJBMrYDTpVGUM/tgpa9SeMOugSabWFq7bg==",
"dev": true
},
+ "@typescript-eslint/typescript-estree": {
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.12.0.tgz",
+ "integrity": "sha512-5bwqLsWBULv1h6pn7cMW5dXX/Y2amRqLaKqsASVwbBHMZSnHqE/HN4vT4fE0aFsiwxYvr98kqOWh1a8ZKXalCQ==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "7.12.0",
+ "@typescript-eslint/visitor-keys": "7.12.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "^9.0.4",
+ "semver": "^7.6.0",
+ "ts-api-utils": "^1.3.0"
+ }
+ },
+ "@typescript-eslint/utils": {
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.12.0.tgz",
+ "integrity": "sha512-Y6hhwxwDx41HNpjuYswYp6gDbkiZ8Hin9Bf5aJQn1bpTs3afYY4GX+MPYxma8jtoIV2GRwTM/UJm/2uGCVv+DQ==",
+ "dev": true,
+ "requires": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@typescript-eslint/scope-manager": "7.12.0",
+ "@typescript-eslint/types": "7.12.0",
+ "@typescript-eslint/typescript-estree": "7.12.0"
+ }
+ },
"@typescript-eslint/visitor-keys": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.11.0.tgz",
- "integrity": "sha512-7syYk4MzjxTEk0g/w3iqtgxnFQspDJfn6QKD36xMuuhTzjcxY7F8EmBLnALjVyaOF1/bVocu3bS/2/F7rXrveQ==",
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.12.0.tgz",
+ "integrity": "sha512-uZk7DevrQLL3vSnfFl5bj4sL75qC9D6EdjemIdbtkuUmIheWpuiiylSY01JxJE7+zGrOWDZrp1WxOuDntvKrHQ==",
"dev": true,
"requires": {
- "@typescript-eslint/types": "7.11.0",
+ "@typescript-eslint/types": "7.12.0",
"eslint-visitor-keys": "^3.4.3"
}
+ },
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "minimatch": {
+ "version": "9.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz",
+ "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
}
}
},
"@typescript-eslint/parser": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.11.0.tgz",
- "integrity": "sha512-yimw99teuaXVWsBcPO1Ais02kwJ1jmNA1KxE7ng0aT7ndr1pT1wqj0OJnsYVGKKlc4QJai86l/025L6z8CljOg==",
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.12.0.tgz",
+ "integrity": "sha512-dm/J2UDY3oV3TKius2OUZIFHsomQmpHtsV0FTh1WO8EKgHLQ1QCADUqscPgTpU+ih1e21FQSRjXckHn3txn6kQ==",
"dev": true,
"requires": {
- "@typescript-eslint/scope-manager": "7.11.0",
- "@typescript-eslint/types": "7.11.0",
- "@typescript-eslint/typescript-estree": "7.11.0",
- "@typescript-eslint/visitor-keys": "7.11.0",
+ "@typescript-eslint/scope-manager": "7.12.0",
+ "@typescript-eslint/types": "7.12.0",
+ "@typescript-eslint/typescript-estree": "7.12.0",
+ "@typescript-eslint/visitor-keys": "7.12.0",
"debug": "^4.3.4"
},
"dependencies": {
"@typescript-eslint/scope-manager": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.11.0.tgz",
- "integrity": "sha512-27tGdVEiutD4POirLZX4YzT180vevUURJl4wJGmm6TrQoiYwuxTIY98PBp6L2oN+JQxzE0URvYlzJaBHIekXAw==",
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.12.0.tgz",
+ "integrity": "sha512-itF1pTnN6F3unPak+kutH9raIkL3lhH1YRPGgt7QQOh43DQKVJXmWkpb+vpc/TiDHs6RSd9CTbDsc/Y+Ygq7kg==",
"dev": true,
"requires": {
- "@typescript-eslint/types": "7.11.0",
- "@typescript-eslint/visitor-keys": "7.11.0"
+ "@typescript-eslint/types": "7.12.0",
+ "@typescript-eslint/visitor-keys": "7.12.0"
}
},
"@typescript-eslint/types": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.11.0.tgz",
- "integrity": "sha512-MPEsDRZTyCiXkD4vd3zywDCifi7tatc4K37KqTprCvaXptP7Xlpdw0NR2hRJTetG5TxbWDB79Ys4kLmHliEo/w==",
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.12.0.tgz",
+ "integrity": "sha512-o+0Te6eWp2ppKY3mLCU+YA9pVJxhUJE15FV7kxuD9jgwIAa+w/ycGJBMrYDTpVGUM/tgpa9SeMOugSabWFq7bg==",
"dev": true
},
"@typescript-eslint/typescript-estree": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.11.0.tgz",
- "integrity": "sha512-cxkhZ2C/iyi3/6U9EPc5y+a6csqHItndvN/CzbNXTNrsC3/ASoYQZEt9uMaEp+xFNjasqQyszp5TumAVKKvJeQ==",
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.12.0.tgz",
+ "integrity": "sha512-5bwqLsWBULv1h6pn7cMW5dXX/Y2amRqLaKqsASVwbBHMZSnHqE/HN4vT4fE0aFsiwxYvr98kqOWh1a8ZKXalCQ==",
"dev": true,
"requires": {
- "@typescript-eslint/types": "7.11.0",
- "@typescript-eslint/visitor-keys": "7.11.0",
+ "@typescript-eslint/types": "7.12.0",
+ "@typescript-eslint/visitor-keys": "7.12.0",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
@@ -26588,12 +26747,12 @@
}
},
"@typescript-eslint/visitor-keys": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.11.0.tgz",
- "integrity": "sha512-7syYk4MzjxTEk0g/w3iqtgxnFQspDJfn6QKD36xMuuhTzjcxY7F8EmBLnALjVyaOF1/bVocu3bS/2/F7rXrveQ==",
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.12.0.tgz",
+ "integrity": "sha512-uZk7DevrQLL3vSnfFl5bj4sL75qC9D6EdjemIdbtkuUmIheWpuiiylSY01JxJE7+zGrOWDZrp1WxOuDntvKrHQ==",
"dev": true,
"requires": {
- "@typescript-eslint/types": "7.11.0",
+ "@typescript-eslint/types": "7.12.0",
"eslint-visitor-keys": "^3.4.3"
}
},
diff --git a/frontend/package.json b/frontend/package.json
index dc37ae33af2d..eaad830ac79d 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -97,8 +97,8 @@
"@ng-select/ng-select": "^12.0.7",
"@ngneat/content-loader": "^7.0.0",
"@ngx-formly/core": "^6.1.4",
- "@openproject/octicons-angular": "^19.13.0",
- "@openproject/primer-view-components": "^0.32.1",
+ "@openproject/octicons-angular": "^19.14.0",
+ "@openproject/primer-view-components": "^0.33.1",
"@openproject/reactivestates": "^3.0.1",
"@primer/css": "^21.2.2",
"@types/hotwired__turbo": "^8.0.1",
@@ -177,6 +177,6 @@
"generate-typings": "tsc -d -p src/tsconfig.app.json"
},
"overrides": {
- "@primer/view-components": "npm:@openproject/primer-view-components@^0.32.1"
+ "@primer/view-components": "npm:@openproject/primer-view-components@^0.33.1"
}
}
diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts
index 31994a02083d..977203c614b9 100644
--- a/frontend/src/app/app.module.ts
+++ b/frontend/src/app/app.module.ts
@@ -151,6 +151,9 @@ import {
import {
AttributeHelpTextComponent,
} from 'core-app/shared/components/attribute-help-texts/attribute-help-text.component';
+import {
+ OpExclusionInfoComponent,
+} from 'core-app/shared/components/fields/display/info/op-exclusion-info.component';
export function initializeServices(injector:Injector) {
return () => {
@@ -334,5 +337,6 @@ export class OpenProjectModule {
registerCustomElement('opce-ckeditor-augmented-textarea', CkeditorAugmentedTextareaComponent, { injector });
registerCustomElement('opce-draggable-autocompleter', DraggableAutocompleteComponent, { injector });
registerCustomElement('opce-attribute-help-text', AttributeHelpTextComponent, { injector });
+ registerCustomElement('opce-exclusion-info', OpExclusionInfoComponent, { injector });
}
}
diff --git a/frontend/src/app/core/config/configuration.service.ts b/frontend/src/app/core/config/configuration.service.ts
index d34618a87039..52d7bd2b2725 100644
--- a/frontend/src/app/core/config/configuration.service.ts
+++ b/frontend/src/app/core/config/configuration.service.ts
@@ -95,6 +95,18 @@ export class ConfigurationService {
return this.systemPreference('dateFormat');
}
+ public hoursPerDay():number {
+ return this.systemPreference('hoursPerDay');
+ }
+
+ public hoursPerWeek():number {
+ return this.systemPreference('hoursPerWeek');
+ }
+
+ public daysPerMonth():number {
+ return this.systemPreference('daysPerMonth');
+ }
+
public timeFormatPresent():boolean {
return !!this.systemPreference('timeFormat');
}
diff --git a/frontend/src/app/core/datetime/timezone.service.ts b/frontend/src/app/core/datetime/timezone.service.ts
index e7a152eb572d..8900b7e9edc6 100644
--- a/frontend/src/app/core/datetime/timezone.service.ts
+++ b/frontend/src/app/core/datetime/timezone.service.ts
@@ -31,6 +31,7 @@ import { ConfigurationService } from 'core-app/core/config/configuration.service
import { I18nService } from 'core-app/core/i18n/i18n.service';
import * as moment from 'moment-timezone';
import { Moment } from 'moment';
+import { outputChronicDuration } from '../../shared/helpers/chronic_duration';
@Injectable({ providedIn: 'root' })
export class TimezoneService {
@@ -115,6 +116,10 @@ export class TimezoneService {
];
}
+ public toSeconds(durationString:string):number {
+ return Number(moment.duration(durationString).asSeconds().toFixed(2));
+ }
+
public toHours(durationString:string):number {
return Number(moment.duration(durationString).asHours().toFixed(2));
}
@@ -130,15 +135,36 @@ export class TimezoneService {
public formattedDuration(durationString:string, unit:'hour'|'days' = 'hour'):string {
switch (unit) {
case 'hour':
- return this.I18n.t('js.units.hour', { count: this.toHours(durationString) });
+ return this.I18n.t('js.units.hour', {
+ count: this.toHours(durationString),
+ });
case 'days':
- return this.I18n.t('js.units.day', { count: this.toDays(durationString) });
+ return this.I18n.t('js.units.day', {
+ count: this.toDays(durationString),
+ });
default:
// Case fallthrough for eslint
return '';
}
}
+ public formattedChronicDuration(durationString:string, opts = {
+ format: 'short',
+ hoursPerDay: this.configurationService.hoursPerDay(),
+ // daysPerWeek is solely a convenience unit for the user's comprehension.
+ // It's not an accepted unit by chronicDuration. daysPerMonth is the value
+ // we provide it.
+ daysPerMonth: this.configurationService.daysPerMonth(),
+ weeks: true,
+ }):string {
+ // Keep in sync with app/services/duration_converter#output
+ const seconds = this.toSeconds(durationString) + 30;
+ const secondsOverflow = seconds % 60;
+ const secondsToTheNearestMinute = seconds - secondsOverflow;
+
+ return outputChronicDuration(secondsToTheNearestMinute, opts) || '0h';
+ }
+
public formattedISODate(date:any):string {
return this.parseDate(date).format('YYYY-MM-DD');
}
diff --git a/frontend/src/app/features/hal/resources/status-resource.ts b/frontend/src/app/features/hal/resources/status-resource.ts
index 504aaf093d2a..d2a5694de3c7 100644
--- a/frontend/src/app/features/hal/resources/status-resource.ts
+++ b/frontend/src/app/features/hal/resources/status-resource.ts
@@ -36,6 +36,8 @@ export class StatusResource extends HalResource {
isReadonly:boolean;
+ excludedFromTotals:boolean;
+
public get state():InputState {
return this.states.statuses.get(this.href as string) as any;
}
diff --git a/frontend/src/app/features/hal/resources/work-package-resource.ts b/frontend/src/app/features/hal/resources/work-package-resource.ts
index 0be3adcfeb47..89fce7c137fd 100644
--- a/frontend/src/app/features/hal/resources/work-package-resource.ts
+++ b/frontend/src/app/features/hal/resources/work-package-resource.ts
@@ -44,6 +44,7 @@ import { HalResource } from 'core-app/features/hal/resources/hal-resource';
import { CollectionResource } from 'core-app/features/hal/resources/collection-resource';
import { TypeResource } from 'core-app/features/hal/resources/type-resource';
import { RelationResource } from 'core-app/features/hal/resources/relation-resource';
+import { StatusResource } from 'core-app/features/hal/resources/status-resource';
import { FormResource } from 'core-app/features/hal/resources/form-resource';
import { Attachable } from 'core-app/features/hal/resources/mixins/attachable-mixin';
import { ICKEditorContext } from 'core-app/shared/components/editor/components/ckeditor/ckeditor.types';
@@ -67,7 +68,7 @@ export interface WorkPackageResourceEmbedded {
relations:CollectionResource;
responsible:HalResource|any;
revisions:CollectionResource|any;
- status:HalResource|any;
+ status:StatusResource|any;
timeEntries:HalResource[]|any[];
type:TypeResource;
version:HalResource|any;
diff --git a/frontend/src/app/shared/components/fields/display/field-types/compound-progress-display-field.module.ts b/frontend/src/app/shared/components/fields/display/field-types/compound-progress-display-field.module.ts
index 4a7d283fcb2b..57a29f7ac857 100644
--- a/frontend/src/app/shared/components/fields/display/field-types/compound-progress-display-field.module.ts
+++ b/frontend/src/app/shared/components/fields/display/field-types/compound-progress-display-field.module.ts
@@ -36,12 +36,16 @@ import {
import {
HierarchyQueryLinkHelperService,
} from 'core-app/shared/components/fields/display/field-types/hierarchy-query-link-helper.service';
+import { ExcludedIconHelperService } from 'core-app/shared/components/fields/display/field-types/excluded-icon-helper.service';
+import { WorkPackageResource } from 'core-app/features/hal/resources/work-package-resource';
export class CompoundProgressDisplayField extends DisplayField {
@InjectField() PathHelper:PathHelperService;
@InjectField() apiV3Service:ApiV3Service;
+ @InjectField() excludedIconHelperService:ExcludedIconHelperService;
+
@InjectField() hierarchyQueryLinkHelper:HierarchyQueryLinkHelperService;
private derivedText = this.I18n.t('js.label_value_derived_from_children');
@@ -65,6 +69,8 @@ export class CompoundProgressDisplayField extends DisplayField {
span.title = this.valueString;
span.classList.add('-actual-value');
+ this.excludedIconHelperService.addIconIfExcludedFromTotals(span, this.resource as WorkPackageResource);
+
element.appendChild(span);
}
diff --git a/frontend/src/app/shared/components/fields/display/field-types/excluded-icon-helper.service.ts b/frontend/src/app/shared/components/fields/display/field-types/excluded-icon-helper.service.ts
new file mode 100644
index 000000000000..3863215923ae
--- /dev/null
+++ b/frontend/src/app/shared/components/fields/display/field-types/excluded-icon-helper.service.ts
@@ -0,0 +1,58 @@
+// -- copyright
+// OpenProject is an open source project management software.
+// Copyright (C) 2012-2024 the OpenProject GmbH
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License version 3.
+//
+// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+// Copyright (C) 2006-2013 Jean-Philippe Lang
+// Copyright (C) 2010-2013 the ChiliProject Team
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// See COPYRIGHT and LICENSE files for more details.
+//++
+
+import { Injectable } from '@angular/core';
+import { ApiV3Service } from 'core-app/core/apiv3/api-v3.service';
+import { WorkPackageResource } from 'core-app/features/hal/resources/work-package-resource';
+import { StatusResource } from 'core-app/features/hal/resources/status-resource';
+
+@Injectable({ providedIn: 'root' })
+
+export class ExcludedIconHelperService {
+ constructor(
+ private apiV3Service:ApiV3Service,
+ ) {}
+
+ public addIconIfExcludedFromTotals(element:HTMLElement, resource:WorkPackageResource):void {
+ if (resource?.status) {
+ this.apiV3Service.statuses.id(resource.status as StatusResource).get().subscribe(
+ (status:StatusResource) => {
+ if (status.excludedFromTotals) {
+ this.addExcludedInfoIcon(element, status.name);
+ }
+ },
+ );
+ }
+ }
+
+ public addExcludedInfoIcon(element:HTMLElement, name:string):void {
+ const infoIcon = document.createElement('opce-exclusion-info');
+ infoIcon.setAttribute('status-name', name);
+ element.appendChild(infoIcon);
+ }
+}
diff --git a/frontend/src/app/shared/components/fields/display/field-types/work-display-field.module.ts b/frontend/src/app/shared/components/fields/display/field-types/work-display-field.module.ts
index bb7414126d03..a7782a1ef807 100644
--- a/frontend/src/app/shared/components/fields/display/field-types/work-display-field.module.ts
+++ b/frontend/src/app/shared/components/fields/display/field-types/work-display-field.module.ts
@@ -31,8 +31,14 @@ import { InjectField } from 'core-app/shared/helpers/angular/inject-field.decora
import { TimezoneService } from 'core-app/core/datetime/timezone.service';
import { ApiV3Service } from 'core-app/core/apiv3/api-v3.service';
import { PathHelperService } from 'core-app/core/path-helper/path-helper.service';
-import { uiStateLinkClass } from 'core-app/features/work-packages/components/wp-fast-table/builders/ui-state-link-builder';
-import { HierarchyQueryLinkHelperService } from 'core-app/shared/components/fields/display/field-types/hierarchy-query-link-helper.service';
+import { ExcludedIconHelperService } from 'core-app/shared/components/fields/display/field-types/excluded-icon-helper.service';
+import { WorkPackageResource } from 'core-app/features/hal/resources/work-package-resource';
+import {
+ uiStateLinkClass,
+} from 'core-app/features/work-packages/components/wp-fast-table/builders/ui-state-link-builder';
+import {
+ HierarchyQueryLinkHelperService,
+} from 'core-app/shared/components/fields/display/field-types/hierarchy-query-link-helper.service';
export class WorkDisplayField extends DisplayField {
@InjectField() timezoneService:TimezoneService;
@@ -41,12 +47,14 @@ export class WorkDisplayField extends DisplayField {
@InjectField() apiV3Service:ApiV3Service;
+ @InjectField() excludedIconHelperService:ExcludedIconHelperService;
+
@InjectField() hierarchyQueryLinkHelper:HierarchyQueryLinkHelperService;
private derivedText = this.I18n.t('js.label_value_derived_from_children');
public get valueString():string {
- return this.timezoneService.formattedDuration(this.value as string);
+ return this.timezoneService.formattedChronicDuration(this.value as string);
}
/**
@@ -65,7 +73,7 @@ export class WorkDisplayField extends DisplayField {
const value = this.derivedValue;
if (value) {
- return this.timezoneService.formattedDuration(value);
+ return this.timezoneService.formattedChronicDuration(value);
}
return this.placeholder;
}
@@ -98,6 +106,9 @@ export class WorkDisplayField extends DisplayField {
}
span.classList.add('-actual-value');
+ if (this.value) {
+ this.excludedIconHelperService.addIconIfExcludedFromTotals(span, this.resource as WorkPackageResource);
+ }
element.appendChild(span);
}
diff --git a/frontend/src/app/shared/components/fields/display/info/op-exclusion-info.component.html b/frontend/src/app/shared/components/fields/display/info/op-exclusion-info.component.html
new file mode 100644
index 000000000000..5c55fa59999c
--- /dev/null
+++ b/frontend/src/app/shared/components/fields/display/info/op-exclusion-info.component.html
@@ -0,0 +1,35 @@
+
+
+
+
+
diff --git a/lookbook/previews/open_project/filter/filters_component_preview.rb b/lookbook/previews/open_project/filter/filters_component_preview.rb
new file mode 100644
index 000000000000..13646dc4fcb7
--- /dev/null
+++ b/lookbook/previews/open_project/filter/filters_component_preview.rb
@@ -0,0 +1,11 @@
+module OpenProject
+ module Filter
+ # @logical_path OpenProject/Filter
+ class FiltersComponentPreview < Lookbook::Preview
+ def default
+ @query = Queries::Projects::ProjectQuery.new
+ render(Projects::ProjectsFiltersComponent.new(query: @query))
+ end
+ end
+ end
+end
diff --git a/modules/avatars/config/locales/crowdin/et.yml b/modules/avatars/config/locales/crowdin/et.yml
index 85920789a83e..ac8e181e58f0 100644
--- a/modules/avatars/config/locales/crowdin/et.yml
+++ b/modules/avatars/config/locales/crowdin/et.yml
@@ -10,7 +10,7 @@ et:
label_choose_avatar: "Choose Avatar from file"
message_avatar_uploaded: "Avatar changed successfully."
error_image_upload: "Error saving the image."
- error_image_size: "The image is too large."
+ error_image_size: "Pilt on liiga suur."
button_change_avatar: "Change avatar"
are_you_sure_delete_avatar: "Are you sure you want to delete your avatar?"
avatar_deleted: "Avatar deleted successfully."
diff --git a/modules/bim/config/locales/crowdin/id.seeders.yml b/modules/bim/config/locales/crowdin/id.seeders.yml
index 8c3340ee9f67..d454cd8579e0 100644
--- a/modules/bim/config/locales/crowdin/id.seeders.yml
+++ b/modules/bim/config/locales/crowdin/id.seeders.yml
@@ -13,7 +13,7 @@ id:
item_2:
name: High
item_3:
- name: Critical
+ name: Kritik
statuses:
item_0:
name: Baru
@@ -42,7 +42,7 @@ id:
item_4:
name: Remark
item_5:
- name: Request
+ name: Permintaan
item_6:
name: Clash
global_queries:
@@ -694,7 +694,7 @@ id:
item_5:
name: Tahapan pencapaian
item_6:
- name: Tasks
+ name: Tugas
item_7:
name: Rencana tim
boards:
@@ -704,7 +704,7 @@ id:
widgets:
item_0:
options:
- name: Welcome
+ name: Selamat datang
item_1:
options:
name: Getting started
diff --git a/modules/bim/config/locales/crowdin/id.yml b/modules/bim/config/locales/crowdin/id.yml
index b09848242bdc..77bc93dfeabe 100644
--- a/modules/bim/config/locales/crowdin/id.yml
+++ b/modules/bim/config/locales/crowdin/id.yml
@@ -107,30 +107,30 @@ id:
uuid_already_taken: "Tidak dapat mengimpor masalah BCF ini karena sudah ada masalah lain dengan GUID yang sama. Mungkinkah masalah BCF ini sudah diimpor ke proyek lain?"
ifc_models:
label_ifc_models: 'Model IFC'
- label_new_ifc_model: 'New IFC model'
- label_show_defaults: 'Show defaults'
- label_default_ifc_models: 'Default IFC models'
- label_edit_defaults: 'Edit defaults'
+ label_new_ifc_model: 'Model IFC baru'
+ label_show_defaults: 'Tampilkan bawaan'
+ label_default_ifc_models: 'Model bawaan IFC'
+ label_edit_defaults: 'Edit pengaturan bawaan'
no_defaults_warning:
- title: 'No IFC model was set as default for this project.'
- check_1: 'Check that you have uploaded at least one IFC model.'
+ title: 'Tidak ada model IFC yang ditetapkan sebagai bawaan dalam projek ini.'
+ check_1: 'Pastikan anda telah mengunggah setidaknya satu model IFC.'
check_2: 'Check that at least one IFC model is set to "Default".'
- no_results: "No IFC models have been uploaded in this project."
+ no_results: "Tidak ada model IFC yang diunggah dalam proyek ini."
conversion_status:
- label: 'Processing?'
- pending: 'Pending'
- processing: 'Processing'
- completed: 'Completed'
+ label: 'Memproses?'
+ pending: 'Menunggu'
+ processing: 'Memproses'
+ completed: 'Selesai'
error: 'Eror'
processing_notice:
- processing_default: 'The following default IFC models are still being processed and are thus not available, yet:'
+ processing_default: 'Model IFC bawaan berikut ini masih diproses dan belum tersedia sekarang:'
flash_messages:
- upload_successful: 'Upload succeeded. It will now get processed and will be ready to use in a couple of minutes.'
+ upload_successful: 'Pengunggahan sukses. File akan diproses dan akan siap digunakan dalam beberapa menit.'
conversion:
- missing_commands: "The following IFC converter commands are missing on this system: %{names}"
+ missing_commands: "Perintah IFC converter berikut ini tidak ditemukan dalam perangkat ini: %{names}\n"
project_module_ifc_models: "Model IFC"
- permission_view_ifc_models: "View IFC models"
- permission_manage_ifc_models: "Import and manage IFC models"
+ permission_view_ifc_models: "Lihat model IFC"
+ permission_manage_ifc_models: "Import dan sesuaikan model IFC"
extraction:
available:
ifc_convert: "IFC conversion pipeline available"
diff --git a/modules/boards/config/locales/crowdin/ar.yml b/modules/boards/config/locales/crowdin/ar.yml
index 85cb3a8ca23b..21ed45cdd902 100644
--- a/modules/boards/config/locales/crowdin/ar.yml
+++ b/modules/boards/config/locales/crowdin/ar.yml
@@ -23,17 +23,17 @@ ar:
basic: Basic
board_type_descriptions:
basic: >
- Start from scratch with a blank board. Manually add cards and columns to this board.
+ ابدأ من الصفر بلوحة فارغة. قم بإضافة البطاقات والأعمدة إلى هذه اللوحة يدويًا.
status: >
- Basic kanban style board with columns for status such as To Do, In Progress, Done.
+ لوحة أساسية بنمط كانبان مع أعمدة للحالة مثل: المهام، قيد التنفيذ، تم الإنجاز.
assignee: >
- Board with automated columns based on assigned users. Ideal for dispatching work packages.
+ لوحة بأعمدة تلقائية بناءً على المستخدمين المعينين. وتعتبر لوحة مثالية لتوزيع حزم العمل.
version: >
- Board with automated columns based on the version attribute. Ideal for planning product development.
+ لوحة بأعمدة تلقائية بناءً على الإصدار. و هي مثالية لتخطيط تطوير المنتجات.
subproject: >
- Board with automated columns for subprojects. Dragging work packages to other lists updates the (sub-)project accordingly.
+ لوحة بأعمدة تلقائية للمشاريع الفرعية. يؤدي سحب حزم العمل إلى قوائم أخرى إلى تحديث المشروع (أو المشروع الفرعي) وفقًا لذلك.
subtasks: >
- Board with automated columns for sub-elements. Dragging work packages to other lists updates the parent accordingly.
+ لوحة بأعمدة تلقائية للعناصر الفرعية. يؤدي سحب حزم العمل إلى قوائم أخرى إلى تحديث العنصر الرئيسي وفقًا لذلك.
upsale:
- teaser_text: 'Would you like to automate your workflows with Boards? Advanced boards are an Enterprise add-on. Please upgrade to a paid plan.'
+ teaser_text: 'هل ترغب في أتمتة سير العمل الخاص بك باستخدام اللوحات؟ اللوحات المتقدمة هي إضافة خاصة بالمؤسسات. يرجى الترقية إلى خطة مدفوعة.'
upgrade: 'الترقية الآن'
diff --git a/modules/boards/config/locales/crowdin/no.yml b/modules/boards/config/locales/crowdin/no.yml
index e233de4921c3..4910340d70cc 100644
--- a/modules/boards/config/locales/crowdin/no.yml
+++ b/modules/boards/config/locales/crowdin/no.yml
@@ -15,7 +15,7 @@
free: Enkel
action: "Handlingstavle (%{attribute})"
board_type_attributes:
- assignee: Deltaker
+ assignee: Utførende
status: Status
version: Versjon
subproject: Underprosjekt
diff --git a/modules/calendar/config/locales/crowdin/ar.yml b/modules/calendar/config/locales/crowdin/ar.yml
index ba85841ad341..2fc8832c8138 100644
--- a/modules/calendar/config/locales/crowdin/ar.yml
+++ b/modules/calendar/config/locales/crowdin/ar.yml
@@ -4,9 +4,9 @@ ar:
name: "OpenProject Calendar"
description: "Provides calendar views."
label_calendar: "التقويم"
- label_calendar_plural: "Calendars"
- label_new_calendar: "New calendar"
+ label_calendar_plural: "التقويمات"
+ label_new_calendar: "تقويم جديد"
permission_view_calendar: "View calendars"
- permission_manage_calendars: "Manage calendars"
- permission_share_calendars: "Subscribe to iCalendars"
- project_module_calendar_view: "Calendars"
+ permission_manage_calendars: "إدارة التقويمات"
+ permission_share_calendars: "الاشتراك في iCalendar"
+ project_module_calendar_view: "التقويمات"
diff --git a/modules/calendar/config/locales/crowdin/et.yml b/modules/calendar/config/locales/crowdin/et.yml
index 826e2f640b47..5a131281ac13 100644
--- a/modules/calendar/config/locales/crowdin/et.yml
+++ b/modules/calendar/config/locales/crowdin/et.yml
@@ -4,9 +4,9 @@ et:
name: "OpenProject Calendar"
description: "Provides calendar views."
label_calendar: "Kalender"
- label_calendar_plural: "Calendars"
- label_new_calendar: "New calendar"
- permission_view_calendar: "View calendars"
- permission_manage_calendars: "Manage calendars"
+ label_calendar_plural: "$Kalendrid"
+ label_new_calendar: "Uus Kalender"
+ permission_view_calendar: "Vaata kalendrit"
+ permission_manage_calendars: "Halda kalendreid"
permission_share_calendars: "Subscribe to iCalendars"
- project_module_calendar_view: "Calendars"
+ project_module_calendar_view: "$Kalendrid"
diff --git a/modules/costs/spec/features/time_entries_spec.rb b/modules/costs/spec/features/time_entries_spec.rb
index 3d6002cc3689..cb0a76abe215 100644
--- a/modules/costs/spec/features/time_entries_spec.rb
+++ b/modules/costs/spec/features/time_entries_spec.rb
@@ -54,7 +54,7 @@
let(:wp_table) { Pages::WorkPackagesTable.new(project) }
let(:query) do
- query = build(:query, user:, project:)
+ query = build(:query, user:, project:)
query.column_names = %w(id subject spent_hours)
query.save!
@@ -73,8 +73,8 @@
parent_row = wp_table.row(parent)
wp_row = wp_table.row(work_package)
- expect(parent_row).to have_css(".inline-edit--container.spentTime", text: "12.5 h")
- expect(wp_row).to have_css(".inline-edit--container.spentTime", text: "2.5 h")
+ expect(parent_row).to have_css(".inline-edit--container.spentTime", text: "1d 4h 30m")
+ expect(wp_row).to have_css(".inline-edit--container.spentTime", text: "2h 30m")
end
it "creates an activity" do
diff --git a/modules/costs/spec/features/view_own_rates_spec.rb b/modules/costs/spec/features/view_own_rates_spec.rb
index ae9d5b4b798f..34c5a072d34d 100644
--- a/modules/costs/spec/features/view_own_rates_spec.rb
+++ b/modules/costs/spec/features/view_own_rates_spec.rb
@@ -109,7 +109,7 @@
it "only displays own entries and rates" do
# All the values do not include the entries made by the other user
- wp_page.expect_attributes spent_time: "1 h",
+ wp_page.expect_attributes spent_time: "1h",
costs_by_type: "2 Translations",
overall_costs: "24.00 EUR",
labor_costs: "10.00 EUR",
diff --git a/modules/documents/app/services/notifications/create_from_model_service/document_strategy.rb b/modules/documents/app/services/notifications/create_from_model_service/document_strategy.rb
index d2855acbcefd..8198cb5470c4 100644
--- a/modules/documents/app/services/notifications/create_from_model_service/document_strategy.rb
+++ b/modules/documents/app/services/notifications/create_from_model_service/document_strategy.rb
@@ -35,15 +35,15 @@ def self.permission
:view_documents
end
- def self.supports_ian?
+ def self.supports_ian?(_reason)
false
end
- def self.supports_mail_digest?
+ def self.supports_mail_digest?(_reason)
false
end
- def self.supports_mail?
+ def self.supports_mail?(_reason)
true
end
diff --git a/modules/gantt/config/locales/crowdin/js-ar.yml b/modules/gantt/config/locales/crowdin/js-ar.yml
index abdce33ccb58..656b1c08ba97 100644
--- a/modules/gantt/config/locales/crowdin/js-ar.yml
+++ b/modules/gantt/config/locales/crowdin/js-ar.yml
@@ -1,6 +1,6 @@
ar:
js:
queries:
- all_open: 'All open'
- timeline: 'Timeline'
- milestones: 'Milestones'
+ all_open: 'كل المفتوح'
+ timeline: 'الخط الزمني'
+ milestones: 'الأحداث الرئيسية'
diff --git a/modules/github_integration/app/components/deploy_targets/row_component.rb b/modules/github_integration/app/components/deploy_targets/row_component.rb
new file mode 100644
index 000000000000..7c51367f4316
--- /dev/null
+++ b/modules/github_integration/app/components/deploy_targets/row_component.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2012-2024 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+module DeployTargets
+ class RowComponent < ::RowComponent # rubocop:disable OpenProject/AddPreviewForViewComponent
+ property :host, :type
+
+ def deploy_target
+ model
+ end
+
+ def created_at
+ helpers.format_time deploy_target.created_at
+ end
+
+ def button_links
+ [delete_link]
+ end
+
+ def delete_link
+ link_to I18n.t(:button_delete),
+ deploy_target_path(deploy_target, back_url: request.fullpath),
+ method: :delete,
+ class: "icon icon-delete"
+ end
+ end
+end
diff --git a/app/contracts/settings/working_days_params_contract.rb b/modules/github_integration/app/components/deploy_targets/table_component.rb
similarity index 71%
rename from app/contracts/settings/working_days_params_contract.rb
rename to modules/github_integration/app/components/deploy_targets/table_component.rb
index 42bacb779bab..2cd46d501f25 100644
--- a/app/contracts/settings/working_days_params_contract.rb
+++ b/modules/github_integration/app/components/deploy_targets/table_component.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2024 the OpenProject GmbH
@@ -26,29 +28,23 @@
# See COPYRIGHT and LICENSE files for more details.
#++
-module Settings
- class WorkingDaysParamsContract < ::ParamsContract
- include RequiresAdminGuard
-
- validate :working_days_are_present
- validate :unique_job
+module DeployTargets
+ class TableComponent < ::TableComponent # rubocop:disable OpenProject/AddPreviewForViewComponent
+ columns :host, :type, :created_at
+ options :current_user
- protected
-
- def working_days_are_present
- if working_days.blank?
- errors.add :base, :working_days_are_missing
- end
+ def initial_sort
+ %i[id asc]
end
- def unique_job
- WorkPackages::ApplyWorkingDaysChangeJob.new.check_concurrency do
- errors.add :base, :previous_working_day_changes_unprocessed
+ def headers
+ columns.map do |name|
+ [name.to_s, header_options(name)]
end
end
- def working_days
- params[:working_days]
+ def header_options(name)
+ { caption: User.human_attribute_name(name) }
end
end
end
diff --git a/spec/contracts/settings/working_days_params_contract_spec.rb b/modules/github_integration/app/controllers/deploy_targets_controller.rb
similarity index 51%
rename from spec/contracts/settings/working_days_params_contract_spec.rb
rename to modules/github_integration/app/controllers/deploy_targets_controller.rb
index ddd60516a286..ed64c7d88fb4 100644
--- a/spec/contracts/settings/working_days_params_contract_spec.rb
+++ b/modules/github_integration/app/controllers/deploy_targets_controller.rb
@@ -26,38 +26,43 @@
# See COPYRIGHT and LICENSE files for more details.
#++
-require "spec_helper"
-require "contracts/shared/model_contract_shared_context"
-
-RSpec.describe Settings::WorkingDaysParamsContract do
- include_context "ModelContract shared context"
- shared_let(:current_user) { create(:admin) }
- let(:setting) { Setting }
- let(:params) { { working_days: [1] } }
- let(:contract) do
- described_class.new(setting, current_user, params:)
- end
+class DeployTargetsController < ApplicationController
+ layout "admin"
- it_behaves_like "contract is valid for active admins and invalid for regular users"
+ before_action :require_admin
- context "without working days" do
- let(:params) { { working_days: [] } }
+ def index
+ @deploy_targets = DeployTarget.all
+ end
- include_examples "contract is invalid", base: :working_days_are_missing
+ def new
+ @deploy_target = DeployTarget.new type: "OpenProject"
end
- context "with an ApplyWorkingDaysChangeJob already existing",
- with_good_job: WorkPackages::ApplyWorkingDaysChangeJob do
- let(:params) { { working_days: [1, 2, 3] } }
+ def create
+ args = params
+ .permit("deploy_target" => ["host", "type", "api_key"])[:deploy_target]
+ .to_h
+ .merge(type: "OpenProject")
+
+ @deploy_target = DeployTarget.create **args
+
+ if @deploy_target.persisted?
+ flash[:success] = I18n.t(:notice_deploy_target_created)
- before do
- WorkPackages::ApplyWorkingDaysChangeJob
- .set(wait: 10.minutes) # GoodJob executes inline job without wait immediately
- .perform_later(user_id: current_user.id,
- previous_non_working_days: [],
- previous_working_days: [1, 2, 3, 4])
+ redirect_to deploy_targets_path
+ else
+ render "new"
end
+ end
+
+ def destroy
+ deploy_target = DeployTarget.find params[:id]
+
+ deploy_target.destroy!
+
+ flash[:success] = I18n.t(:notice_deploy_target_destroyed)
- include_examples "contract is invalid", base: :previous_working_day_changes_unprocessed
+ redirect_to deploy_targets_path
end
end
diff --git a/modules/github_integration/app/models/deploy_status_check.rb b/modules/github_integration/app/models/deploy_status_check.rb
new file mode 100644
index 000000000000..670bfb321ad5
--- /dev/null
+++ b/modules/github_integration/app/models/deploy_status_check.rb
@@ -0,0 +1,40 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2012-2024 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+class DeployStatusCheck < ApplicationRecord
+ belongs_to :github_pull_request
+ belongs_to :deploy_target
+
+ validates_presence_of :core_sha
+
+ delegate :merge_commit_sha, to: :github_pull_request
+
+ def pull_request
+ github_pull_request
+ end
+end
diff --git a/modules/github_integration/app/models/deploy_target.rb b/modules/github_integration/app/models/deploy_target.rb
new file mode 100644
index 000000000000..cb4d5942193e
--- /dev/null
+++ b/modules/github_integration/app/models/deploy_target.rb
@@ -0,0 +1,43 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2012-2024 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+class DeployTarget < ApplicationRecord
+ self.inheritance_column = nil
+
+ store_accessor :options, :api_key
+
+ has_many :deploy_status_checks, dependent: :destroy
+
+ validates_presence_of :host
+ validates_uniqueness_of :host
+
+ validates_presence_of :type
+
+ # this is very much specific to the only type of target we support for now, OpenProject
+ validates_presence_of :api_key
+end
diff --git a/modules/github_integration/app/models/github_pull_request.rb b/modules/github_integration/app/models/github_pull_request.rb
index 4b53509d7ba1..5cef02b4dfbd 100644
--- a/modules/github_integration/app/models/github_pull_request.rb
+++ b/modules/github_integration/app/models/github_pull_request.rb
@@ -31,12 +31,14 @@ class GithubPullRequest < ApplicationRecord
has_and_belongs_to_many :work_packages
has_many :github_check_runs, dependent: :destroy
+ has_many :deploy_status_checks, dependent: :destroy
belongs_to :github_user, optional: true
belongs_to :merged_by, optional: true, class_name: "GithubUser"
enum state: {
open: "open",
- closed: "closed"
+ closed: "closed",
+ deployed: "deployed"
}
validates_presence_of :github_html_url,
diff --git a/modules/github_integration/app/views/deploy_targets/_form.html.erb b/modules/github_integration/app/views/deploy_targets/_form.html.erb
new file mode 100644
index 000000000000..34c7efcf5744
--- /dev/null
+++ b/modules/github_integration/app/views/deploy_targets/_form.html.erb
@@ -0,0 +1,58 @@
+<%#-- copyright
+OpenProject is an open source project management software.
+Copyright (C) 2012-2024 the OpenProject GmbH
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License version 3.
+
+OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+Copyright (C) 2006-2013 Jean-Philippe Lang
+Copyright (C) 2010-2013 the ChiliProject Team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+See COPYRIGHT and LICENSE files for more details.
+
+++#%>
+
+
+
diff --git a/modules/github_integration/app/views/deploy_targets/index.html.erb b/modules/github_integration/app/views/deploy_targets/index.html.erb
new file mode 100644
index 000000000000..1b564473e841
--- /dev/null
+++ b/modules/github_integration/app/views/deploy_targets/index.html.erb
@@ -0,0 +1,40 @@
+<%#-- copyright
+OpenProject is an open source project management software.
+Copyright (C) 2012-2024 the OpenProject GmbH
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License version 3.
+
+OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+Copyright (C) 2006-2013 Jean-Philippe Lang
+Copyright (C) 2010-2013 the ChiliProject Team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+See COPYRIGHT and LICENSE files for more details.
+
+++#%>
+
+<% html_title t(:label_administration), t(:label_github_integration) %>
+<%= toolbar title: t(:label_deploy_target_plural) do %>
+
+<% end %>
+
+<%= render DeployTargets::TableComponent.new(rows: @deploy_targets, current_user: ) %>
diff --git a/modules/github_integration/app/views/deploy_targets/new.html.erb b/modules/github_integration/app/views/deploy_targets/new.html.erb
new file mode 100644
index 000000000000..f47dcca016da
--- /dev/null
+++ b/modules/github_integration/app/views/deploy_targets/new.html.erb
@@ -0,0 +1,40 @@
+<%#-- copyright
+OpenProject is an open source project management software.
+Copyright (C) 2012-2024 the OpenProject GmbH
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License version 3.
+
+OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+Copyright (C) 2006-2013 Jean-Philippe Lang
+Copyright (C) 2010-2013 the ChiliProject Team
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+See COPYRIGHT and LICENSE files for more details.
+
+++#%>
+
+<% html_title t(:label_administration), t("label_deploy_target_new") %>
+<% local_assigns[:additional_breadcrumb] = t(:label_deploy_target_new) %>
+
+<%= toolbar title: t(:label_deploy_target_new) %>
+
+<%= error_messages_for @deploy_target %>
+
+<%= labelled_tabular_form_for @deploy_target, url: deploy_targets_path do |f| %>
+ <%= render partial: 'deploy_targets/form', locals: { f: f, deploy_target: @deploy_target } %>
+ <%= styled_button_tag t(:button_save), class: '-highlight -with-icon icon-checkmark' %>
+<% end %>
diff --git a/modules/github_integration/app/workers/cron/check_deploy_status_job.rb b/modules/github_integration/app/workers/cron/check_deploy_status_job.rb
new file mode 100644
index 000000000000..1372811aa5d0
--- /dev/null
+++ b/modules/github_integration/app/workers/cron/check_deploy_status_job.rb
@@ -0,0 +1,193 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2012-2024 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+module Cron
+ class CheckDeployStatusJob < ApplicationJob
+ include OpenProject::GithubIntegration::NotificationHandler::Helper
+
+ priority_number :low
+
+ def perform
+ deploy_targets.find_each do |deploy_target|
+ sha = openproject_core_sha deploy_target.host, deploy_target.api_key
+
+ if sha.present?
+ pull_requests.find_each do |pull_request|
+ check_deploy_status deploy_target, pull_request, sha
+ end
+ else
+ OpenProject.logger.error "Failed to retrieve core SHA for deploy target #{deploy_target.host}"
+ end
+ end
+ end
+
+ def deploy_targets
+ DeployTarget.all
+ end
+
+ def pull_requests
+ GithubPullRequest
+ .closed
+ .where.not(merge_commit_sha: nil)
+ end
+
+ def check_deploy_status(deploy_target, pull_request, core_sha)
+ status_check = deploy_status_check deploy_target, pull_request
+
+ # we already checked this PR against the given core SHA, so no need to check again
+ return if status_check.core_sha == core_sha
+
+ # if the commit is contained, it has been deployed
+ if commit_contains? core_sha, pull_request.merge_commit_sha
+ update_deploy_status pull_request, deploy_target
+ else
+ status_check.update core_sha: # remember last checked SHA to not check twice
+ end
+ end
+
+ ##
+ # Marks the given PR as deployed and removes the last status check
+ # as it won't be needed anymore. This is because only closed (not yet deployed)
+ # PRs are ever checked for their deployment status.
+ def update_deploy_status(pull_request, deploy_target)
+ host = deploy_target.host
+
+ ActiveRecord::Base.transaction do
+ delete_status_check pull_request, deploy_target
+ pull_request.update! state: "deployed"
+
+ comment_on_referenced_work_packages(
+ pull_request.work_packages,
+ comment_user,
+ "[#{pull_request.repository}##{pull_request.number}](#{pull_request.github_html_url}) deployed to [#{host}](https://#{host})"
+ )
+ end
+ end
+
+ def delete_status_check(pull_request, deploy_target)
+ # we use `select` and delete it this way to also cover
+ # not-yet-persisted records
+ checks = pull_request
+ .deploy_status_checks
+ .select { |c| c.deploy_target == deploy_target }
+
+ pull_request.deploy_status_checks.delete(checks)
+ end
+
+ ##
+ # Ideally this would be the github user, but we don't really have a way
+ # to identify it outside of the webhook request cycle.
+ def comment_user
+ User.system
+ end
+
+ def deploy_status_check(deploy_target, pull_request)
+ pull_request
+ .deploy_status_checks
+ .find_or_initialize_by(
+ deploy_target:,
+ github_pull_request: pull_request
+ )
+ end
+
+ def openproject_core_sha(host, api_token)
+ res = introspection_request(host, api_token)
+
+ return nil if handle_request_error res, "Could not get OpenProject core SHA"
+
+ info = JSON.parse res.body.to_s
+
+ info["coreSha"].presence
+ end
+
+ def introspection_request(host, api_token)
+ OpenProject.httpx.basic_auth("apikey", api_token).get("http://#{host}/api/v3")
+ end
+
+ ##
+ # Uses the GitHub APIs compare endpoint to compare the currently deployed base commit
+ # and a merge commit from a PR.
+ #
+ # If the latter is included in the former, there will be 'ahead_by' and 'behind_by'
+ # in the response. 'aheady_by' will be 0, 'behind_by' greater than 0.
+ #
+ # If the commits are not included in the same branch, these fields
+ # will not be present at all.
+ def commit_contains?(base_commit_sha, merge_commit_sha)
+ data = compare_commits base_commit_sha, merge_commit_sha
+
+ return false if data.nil?
+
+ status_identical?(data) || status_behind?(data)
+ end
+
+ def status_identical?(data)
+ status = data["status"].presence
+
+ status == "identical"
+ end
+
+ def status_behind?(data)
+ status = data["status"].presence
+ ahead_by = data["ahead_by"].presence
+ behind_by = data["behind_by"].presence
+
+ status == "behind" && ahead_by == 0 && (behind_by.present? && behind_by > 0)
+ end
+
+ def compare_commits(sha_a, sha_b)
+ res = compare_commits_request sha_a, sha_b
+
+ return nil if handle_request_error res, "Failed to compare commits"
+
+ JSON.parse res.body.read
+ end
+
+ def handle_request_error(res, error_prefix)
+ if res.is_a? HTTPX::ErrorResponse
+ OpenProject.logger.error "#{error_prefix}: #{res.error}"
+ elsif res.status == 404
+ OpenProject.logger.error "#{error_prefix}: not found"
+ elsif res.status != 200
+ OpenProject.logger.error "#{error_prefix}: #{res.body}"
+ else
+ return false
+ end
+
+ true
+ end
+
+ def compare_commits_request(sha_a, sha_b)
+ OpenProject.httpx.get(compare_commits_url(sha_a, sha_b))
+ end
+
+ def compare_commits_url(sha_a, sha_b)
+ "https://api.github.com/repos/opf/openproject/compare/#{sha_a}...#{sha_b}"
+ end
+ end
+end
diff --git a/modules/github_integration/config/locales/crowdin/af.yml b/modules/github_integration/config/locales/crowdin/af.yml
index bf078ba5074f..a50b60d7fd63 100644
--- a/modules/github_integration/config/locales/crowdin/af.yml
+++ b/modules/github_integration/config/locales/crowdin/af.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
af:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/ar.yml b/modules/github_integration/config/locales/crowdin/ar.yml
index 1d9a37fda1ff..898406d566ac 100644
--- a/modules/github_integration/config/locales/crowdin/ar.yml
+++ b/modules/github_integration/config/locales/crowdin/ar.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
ar:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
- permission_show_github_content: "Show GitHub content"
+ permission_show_github_content: "عرض محتوى GitHub"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/az.yml b/modules/github_integration/config/locales/crowdin/az.yml
index 39d4f01f4312..14c738320d54 100644
--- a/modules/github_integration/config/locales/crowdin/az.yml
+++ b/modules/github_integration/config/locales/crowdin/az.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
az:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/be.yml b/modules/github_integration/config/locales/crowdin/be.yml
index ecca59cddb7d..0ed3f730b28f 100644
--- a/modules/github_integration/config/locales/crowdin/be.yml
+++ b/modules/github_integration/config/locales/crowdin/be.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
be:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/bg.yml b/modules/github_integration/config/locales/crowdin/bg.yml
index 2951ef2ed5c1..ef87dda6866b 100644
--- a/modules/github_integration/config/locales/crowdin/bg.yml
+++ b/modules/github_integration/config/locales/crowdin/bg.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
bg:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/ca.yml b/modules/github_integration/config/locales/crowdin/ca.yml
index 281de70a9e8c..f9295b89a765 100644
--- a/modules/github_integration/config/locales/crowdin/ca.yml
+++ b/modules/github_integration/config/locales/crowdin/ca.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
ca:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Mostra el contingut de GitHub"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/ckb-IR.yml b/modules/github_integration/config/locales/crowdin/ckb-IR.yml
index a196a2b20966..e49f8f07b4c1 100644
--- a/modules/github_integration/config/locales/crowdin/ckb-IR.yml
+++ b/modules/github_integration/config/locales/crowdin/ckb-IR.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
ckb-IR:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/cs.yml b/modules/github_integration/config/locales/crowdin/cs.yml
index 29da6e2a4b86..2701b1a04370 100644
--- a/modules/github_integration/config/locales/crowdin/cs.yml
+++ b/modules/github_integration/config/locales/crowdin/cs.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
cs:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub integrace"
description: "Integruje OpenProject a GitHub pro lepší workflow"
project_module_github: "GitHub"
permission_show_github_content: "Zobrazit GitHub obsah"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/da.yml b/modules/github_integration/config/locales/crowdin/da.yml
index 63535f8c8bff..eb951a74bf1d 100644
--- a/modules/github_integration/config/locales/crowdin/da.yml
+++ b/modules/github_integration/config/locales/crowdin/da.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
da:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Vis GitHub indhold"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/de.yml b/modules/github_integration/config/locales/crowdin/de.yml
index 90e23bd57458..27c5349f54fc 100644
--- a/modules/github_integration/config/locales/crowdin/de.yml
+++ b/modules/github_integration/config/locales/crowdin/de.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
de:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub-Integration"
description: "Integriert OpenProject und GitHub für einen besseren Arbeitsablauf"
project_module_github: "GitHub"
permission_show_github_content: "Zeige weiteren Inhalt"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/el.yml b/modules/github_integration/config/locales/crowdin/el.yml
index d0ff03cb836e..5dbd8258fc84 100644
--- a/modules/github_integration/config/locales/crowdin/el.yml
+++ b/modules/github_integration/config/locales/crowdin/el.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
el:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Εμφάνιση περιεχομένου GitHub"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/eo.yml b/modules/github_integration/config/locales/crowdin/eo.yml
index 2a3c878fcb6e..30283f1c7ffb 100644
--- a/modules/github_integration/config/locales/crowdin/eo.yml
+++ b/modules/github_integration/config/locales/crowdin/eo.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
eo:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/es.yml b/modules/github_integration/config/locales/crowdin/es.yml
index 054612a72417..7e0cf3cbeba5 100644
--- a/modules/github_integration/config/locales/crowdin/es.yml
+++ b/modules/github_integration/config/locales/crowdin/es.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
es:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "Integración de OpenProject y GitHub"
description: "Integra OpenProject y GitHub para un mejor flujo de trabajo"
project_module_github: "GitHub"
permission_show_github_content: "Mostrar contenido de GitHub"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/et.yml b/modules/github_integration/config/locales/crowdin/et.yml
index 2f044d80b514..07a614243bce 100644
--- a/modules/github_integration/config/locales/crowdin/et.yml
+++ b/modules/github_integration/config/locales/crowdin/et.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
et:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/eu.yml b/modules/github_integration/config/locales/crowdin/eu.yml
index a6fc297c2037..2d925faa3b64 100644
--- a/modules/github_integration/config/locales/crowdin/eu.yml
+++ b/modules/github_integration/config/locales/crowdin/eu.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
eu:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/fa.yml b/modules/github_integration/config/locales/crowdin/fa.yml
index 23756ff7fe35..4bfebe337745 100644
--- a/modules/github_integration/config/locales/crowdin/fa.yml
+++ b/modules/github_integration/config/locales/crowdin/fa.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
fa:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/fi.yml b/modules/github_integration/config/locales/crowdin/fi.yml
index 45427fba8763..d8b69535e9f2 100644
--- a/modules/github_integration/config/locales/crowdin/fi.yml
+++ b/modules/github_integration/config/locales/crowdin/fi.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
fi:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/fil.yml b/modules/github_integration/config/locales/crowdin/fil.yml
index 53862d954cbe..d2460144746d 100644
--- a/modules/github_integration/config/locales/crowdin/fil.yml
+++ b/modules/github_integration/config/locales/crowdin/fil.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
fil:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/fr.yml b/modules/github_integration/config/locales/crowdin/fr.yml
index e7756809697a..b8391722e13f 100644
--- a/modules/github_integration/config/locales/crowdin/fr.yml
+++ b/modules/github_integration/config/locales/crowdin/fr.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
fr:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "Intégration de GitHub et OpenProject"
description: "Permet une intégration étroite entre OpenProject et GitHub pour un meilleur flux de travail"
project_module_github: "GitHub"
permission_show_github_content: "Afficher le contenu GitHub"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/he.yml b/modules/github_integration/config/locales/crowdin/he.yml
index b2dc75766e5f..57965b9f3a7f 100644
--- a/modules/github_integration/config/locales/crowdin/he.yml
+++ b/modules/github_integration/config/locales/crowdin/he.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
he:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/hi.yml b/modules/github_integration/config/locales/crowdin/hi.yml
index c2c206940e38..9a54ed36ce3d 100644
--- a/modules/github_integration/config/locales/crowdin/hi.yml
+++ b/modules/github_integration/config/locales/crowdin/hi.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
hi:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/hr.yml b/modules/github_integration/config/locales/crowdin/hr.yml
index 34ec7803ff4a..9fb9e050f445 100644
--- a/modules/github_integration/config/locales/crowdin/hr.yml
+++ b/modules/github_integration/config/locales/crowdin/hr.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
hr:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/hu.yml b/modules/github_integration/config/locales/crowdin/hu.yml
index e25a58801b7b..95f163b045af 100644
--- a/modules/github_integration/config/locales/crowdin/hu.yml
+++ b/modules/github_integration/config/locales/crowdin/hu.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
hu:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "GitHub tartalom mutatása"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/id.yml b/modules/github_integration/config/locales/crowdin/id.yml
index f7e8c79d0ac2..3c2130025b73 100644
--- a/modules/github_integration/config/locales/crowdin/id.yml
+++ b/modules/github_integration/config/locales/crowdin/id.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
id:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Tampilkan konten GitHub"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/it.yml b/modules/github_integration/config/locales/crowdin/it.yml
index d2b0ecda8dec..e1dcd0ff21ef 100644
--- a/modules/github_integration/config/locales/crowdin/it.yml
+++ b/modules/github_integration/config/locales/crowdin/it.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
it:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "Integrazione OpenProject GitHub"
description: "Integra OpenProject e GitHub per un migliore flusso di lavoro"
project_module_github: "GitHub"
permission_show_github_content: "Mostra il contenuto di GitHub"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/ja.yml b/modules/github_integration/config/locales/crowdin/ja.yml
index ba104b1a6e78..26401ac03dcc 100644
--- a/modules/github_integration/config/locales/crowdin/ja.yml
+++ b/modules/github_integration/config/locales/crowdin/ja.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
ja:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "GitHub コンテンツを表示する"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/js-ar.yml b/modules/github_integration/config/locales/crowdin/js-ar.yml
index ab342782a5a7..c1c99c6b5a24 100644
--- a/modules/github_integration/config/locales/crowdin/js-ar.yml
+++ b/modules/github_integration/config/locales/crowdin/js-ar.yml
@@ -40,12 +40,12 @@ ar:
empty: 'There are no pull requests linked yet. Link an existing PR by using the code OP#%{wp_id} in the PR description or create a new PR.'
github_actions: Actions
pull_requests:
- message: "Pull request #%{pr_number} %{pr_link} for %{repository_link} authored by %{github_user_link} has been %{pr_state}."
- merged_message: "Pull request #%{pr_number} %{pr_link} for %{repository_link} has been %{pr_state} by %{github_user_link}."
- referenced_message: "Pull request #%{pr_number} %{pr_link} for %{repository_link} authored by %{github_user_link} referenced this work package."
+ message: "طلب السحب #%{pr_number} %{pr_link} لمستودع %{repository_link} الذي أنشأه %{github_user_link} تم %{pr_state}."
+ merged_message: "طلب السحب #%{pr_number} %{pr_link} لمستودع %{repository_link} تم %{pr_state} من قبل %{github_user_link}."
+ referenced_message: "طلب السحب #%{pr_number} %{pr_link} لمستودع %{repository_link} الذي أنشأه %{github_user_link} أشار إلى حزمة العمل هذه."
states:
- opened: 'opened'
+ opened: 'مفتوح'
closed: 'مغلق'
- draft: 'drafted'
- merged: 'merged'
- ready_for_review: 'marked ready for review'
+ draft: 'تمت صياغته'
+ merged: 'مدمج'
+ ready_for_review: 'تم وضع علامة جاهز للمراجعة'
diff --git a/modules/github_integration/config/locales/crowdin/ka.yml b/modules/github_integration/config/locales/crowdin/ka.yml
index 853ae6c0e2e7..e82e553a0c95 100644
--- a/modules/github_integration/config/locales/crowdin/ka.yml
+++ b/modules/github_integration/config/locales/crowdin/ka.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
ka:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/kk.yml b/modules/github_integration/config/locales/crowdin/kk.yml
index e0826ee9b562..1709043c43ed 100644
--- a/modules/github_integration/config/locales/crowdin/kk.yml
+++ b/modules/github_integration/config/locales/crowdin/kk.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
kk:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/ko.yml b/modules/github_integration/config/locales/crowdin/ko.yml
index 2bad6ba92add..1ff41a30cb75 100644
--- a/modules/github_integration/config/locales/crowdin/ko.yml
+++ b/modules/github_integration/config/locales/crowdin/ko.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
ko:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub 통합"
description: "개선된 워크플로를 위해 OpenProject와 GitHub를 통합합니다"
project_module_github: "GitHub"
permission_show_github_content: "GitHub 콘텐츠 표시"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/lt.yml b/modules/github_integration/config/locales/crowdin/lt.yml
index 712dcedd15d5..d785406d8b54 100644
--- a/modules/github_integration/config/locales/crowdin/lt.yml
+++ b/modules/github_integration/config/locales/crowdin/lt.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
lt:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub integracija"
description: "Integruoja OpenProject ir GitHub geresniems procesams"
project_module_github: "GitHub"
permission_show_github_content: "Parodyti GitHub turinį"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/lv.yml b/modules/github_integration/config/locales/crowdin/lv.yml
index 2dce3eb5dae2..285956e3e20a 100644
--- a/modules/github_integration/config/locales/crowdin/lv.yml
+++ b/modules/github_integration/config/locales/crowdin/lv.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
lv:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/mn.yml b/modules/github_integration/config/locales/crowdin/mn.yml
index 6750905a8175..499560dd9975 100644
--- a/modules/github_integration/config/locales/crowdin/mn.yml
+++ b/modules/github_integration/config/locales/crowdin/mn.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
mn:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/ms.yml b/modules/github_integration/config/locales/crowdin/ms.yml
index 4d24deee6a10..5194c5899f6a 100644
--- a/modules/github_integration/config/locales/crowdin/ms.yml
+++ b/modules/github_integration/config/locales/crowdin/ms.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
ms:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "Integrasi GitHub OpenProject"
description: "Mengintegrasikan OpenProject dan GitHub untuk aliran kerja yang lebih baik"
project_module_github: "GitHub"
permission_show_github_content: "Paparkan kandungan GitHub"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/ne.yml b/modules/github_integration/config/locales/crowdin/ne.yml
index 8933e430608a..703c0bb0a1e8 100644
--- a/modules/github_integration/config/locales/crowdin/ne.yml
+++ b/modules/github_integration/config/locales/crowdin/ne.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
ne:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/nl.yml b/modules/github_integration/config/locales/crowdin/nl.yml
index 7f46d226eed6..ee4ec41dd907 100644
--- a/modules/github_integration/config/locales/crowdin/nl.yml
+++ b/modules/github_integration/config/locales/crowdin/nl.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
nl:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Toon GitHub inhoud"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/no.yml b/modules/github_integration/config/locales/crowdin/no.yml
index ee9779d1b1df..f24b4677792a 100644
--- a/modules/github_integration/config/locales/crowdin/no.yml
+++ b/modules/github_integration/config/locales/crowdin/no.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
"no":
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub integrasjon"
description: "Integrerer OpenProject og GitHub for en bedre arbeidsflyt"
project_module_github: "GitHub"
permission_show_github_content: "Vis GitHub innhold"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/pl.yml b/modules/github_integration/config/locales/crowdin/pl.yml
index 366ff3450d18..ebd3fe849c7d 100644
--- a/modules/github_integration/config/locales/crowdin/pl.yml
+++ b/modules/github_integration/config/locales/crowdin/pl.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
pl:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "Integracja OpenProject z GitHub"
description: "Integruje OpenProject i GitHub dla lepszego przepływu pracy"
project_module_github: "GitHub"
permission_show_github_content: "Pokaż treść GitHub"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/pt-BR.yml b/modules/github_integration/config/locales/crowdin/pt-BR.yml
index a623297c3791..6537addd962d 100644
--- a/modules/github_integration/config/locales/crowdin/pt-BR.yml
+++ b/modules/github_integration/config/locales/crowdin/pt-BR.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
pt-BR:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "Integração do OpenProject GitHub"
description: "Integra o OpenProject e o GitHub para um melhor fluxo de trabalho"
project_module_github: "GitHub"
permission_show_github_content: "Exibir conteúdo GitHub"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/pt-PT.yml b/modules/github_integration/config/locales/crowdin/pt-PT.yml
index 319a17c6e6a0..f2c6faa6be1d 100644
--- a/modules/github_integration/config/locales/crowdin/pt-PT.yml
+++ b/modules/github_integration/config/locales/crowdin/pt-PT.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
pt-PT:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "Integração do OpenProject GitHub"
description: "Integra o OpenProject e o GitHub para um melhor fluxo de trabalho"
project_module_github: "GitHub"
permission_show_github_content: "Mostrar conteúdo GitHub"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/ro.yml b/modules/github_integration/config/locales/crowdin/ro.yml
index 322fb50887f2..f60b02ab23c0 100644
--- a/modules/github_integration/config/locales/crowdin/ro.yml
+++ b/modules/github_integration/config/locales/crowdin/ro.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
ro:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Afișați conținutul GitHub"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/ru.yml b/modules/github_integration/config/locales/crowdin/ru.yml
index 222a47827d9c..003a9741bdfd 100644
--- a/modules/github_integration/config/locales/crowdin/ru.yml
+++ b/modules/github_integration/config/locales/crowdin/ru.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
ru:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "Интеграция с OpenProject GitHub"
description: "Интегрирует OpenProject и GitHub для лучшего рабочего процесса"
project_module_github: "GitHub"
permission_show_github_content: "Показать контент GitHub"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/rw.yml b/modules/github_integration/config/locales/crowdin/rw.yml
index a42bca3db70d..8a5009d3e822 100644
--- a/modules/github_integration/config/locales/crowdin/rw.yml
+++ b/modules/github_integration/config/locales/crowdin/rw.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
rw:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/si.yml b/modules/github_integration/config/locales/crowdin/si.yml
index f06ef5264ae2..5dd3bd30f9e5 100644
--- a/modules/github_integration/config/locales/crowdin/si.yml
+++ b/modules/github_integration/config/locales/crowdin/si.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
si:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/sk.yml b/modules/github_integration/config/locales/crowdin/sk.yml
index 833ddae134c3..5ad998b0ac80 100644
--- a/modules/github_integration/config/locales/crowdin/sk.yml
+++ b/modules/github_integration/config/locales/crowdin/sk.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
sk:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/sl.yml b/modules/github_integration/config/locales/crowdin/sl.yml
index 483112f142f5..dc3bd69181cb 100644
--- a/modules/github_integration/config/locales/crowdin/sl.yml
+++ b/modules/github_integration/config/locales/crowdin/sl.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
sl:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Pokaži GitHub vsebino"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/sr.yml b/modules/github_integration/config/locales/crowdin/sr.yml
index 3cf9eed05324..d6ba7ce2ebb3 100644
--- a/modules/github_integration/config/locales/crowdin/sr.yml
+++ b/modules/github_integration/config/locales/crowdin/sr.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
sr:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/sv.yml b/modules/github_integration/config/locales/crowdin/sv.yml
index 95999c5cf523..ba84910b2e73 100644
--- a/modules/github_integration/config/locales/crowdin/sv.yml
+++ b/modules/github_integration/config/locales/crowdin/sv.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
sv:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/th.yml b/modules/github_integration/config/locales/crowdin/th.yml
index fb54c5c421b4..3cd44effbc8a 100644
--- a/modules/github_integration/config/locales/crowdin/th.yml
+++ b/modules/github_integration/config/locales/crowdin/th.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
th:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "แสดงเนื้อหา GitHub "
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/tr.yml b/modules/github_integration/config/locales/crowdin/tr.yml
index 55573af1443c..b07857734afb 100644
--- a/modules/github_integration/config/locales/crowdin/tr.yml
+++ b/modules/github_integration/config/locales/crowdin/tr.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
tr:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Entegrasyonu"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Github içeriğini göster"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/uk.yml b/modules/github_integration/config/locales/crowdin/uk.yml
index 75c9840641e9..c7524bb03581 100644
--- a/modules/github_integration/config/locales/crowdin/uk.yml
+++ b/modules/github_integration/config/locales/crowdin/uk.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
uk:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "Інтеграція OpenProject GitHub"
description: "Інтегрує OpenProject і GitHub для покращення робочого процесу"
project_module_github: "GitHub"
permission_show_github_content: "Показати контент GitHub"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/uz.yml b/modules/github_integration/config/locales/crowdin/uz.yml
index a56b43bc7f59..afc55646cf9e 100644
--- a/modules/github_integration/config/locales/crowdin/uz.yml
+++ b/modules/github_integration/config/locales/crowdin/uz.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
uz:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/vi.yml b/modules/github_integration/config/locales/crowdin/vi.yml
index 0127650d8340..9e14e2e70dab 100644
--- a/modules/github_integration/config/locales/crowdin/vi.yml
+++ b/modules/github_integration/config/locales/crowdin/vi.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
vi:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Hiển thị nội dung GitHub"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/zh-CN.yml b/modules/github_integration/config/locales/crowdin/zh-CN.yml
index a37088622f53..80299b66e3e1 100644
--- a/modules/github_integration/config/locales/crowdin/zh-CN.yml
+++ b/modules/github_integration/config/locales/crowdin/zh-CN.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
zh-CN:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub 集成"
description: "将 OpenProject 和 GitHub 进行集成,以实现更好的工作流程。"
project_module_github: "GitHub"
permission_show_github_content: "显示 GitHub 内容"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/crowdin/zh-TW.yml b/modules/github_integration/config/locales/crowdin/zh-TW.yml
index 15c4247585b6..138bb92750de 100644
--- a/modules/github_integration/config/locales/crowdin/zh-TW.yml
+++ b/modules/github_integration/config/locales/crowdin/zh-TW.yml
@@ -20,8 +20,20 @@
#See COPYRIGHT and LICENSE files for more details.
#++
zh-TW:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub 整合"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "顯示 GitHub 內容"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url) belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/locales/en.yml b/modules/github_integration/config/locales/en.yml
index 8b5a2e3e6dcf..182110277b56 100644
--- a/modules/github_integration/config/locales/en.yml
+++ b/modules/github_integration/config/locales/en.yml
@@ -27,9 +27,22 @@
#++
en:
+ button_add_deploy_target: Add deploy target
+ label_deploy_target: Deploy target
+ label_deploy_target_new: New deploy target
+ label_deploy_target_plural: Deploy targets
+ label_github_integration: GitHub Integration
+ notice_deploy_target_created: Deploy target created
+ notice_deploy_target_destroyed: Deploy target deleted
plugin_openproject_github_integration:
name: "OpenProject GitHub Integration"
description: "Integrates OpenProject and GitHub for a better workflow"
project_module_github: "GitHub"
permission_show_github_content: "Show GitHub content"
+ permission_introspection: Read running OpenProject core version and build SHA
+ text_deploy_target_type_info: >
+ So far we only support OpenProject itself.
+ text_deploy_target_api_key_info: >
+ An OpenProject [API key](docs_url)
+ belonging to a user who has the global introspection permission.
diff --git a/modules/github_integration/config/routes.rb b/modules/github_integration/config/routes.rb
new file mode 100644
index 000000000000..2f6f23ab8f4e
--- /dev/null
+++ b/modules/github_integration/config/routes.rb
@@ -0,0 +1,31 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2012-2024 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+Rails.application.routes.draw do
+ resources :deploy_targets, only: %i[index new create destroy]
+end
diff --git a/modules/github_integration/db/migrate/20240501083852_create_deploy_targets.rb b/modules/github_integration/db/migrate/20240501083852_create_deploy_targets.rb
new file mode 100644
index 000000000000..782e976724bb
--- /dev/null
+++ b/modules/github_integration/db/migrate/20240501083852_create_deploy_targets.rb
@@ -0,0 +1,13 @@
+class CreateDeployTargets < ActiveRecord::Migration[7.1]
+ def change
+ create_table :deploy_targets do |t|
+ t.text :type, null: false
+ t.text :host, null: false
+ t.jsonb :options, null: false, default: {}
+
+ t.timestamps
+ end
+
+ add_index :deploy_targets, :host, unique: true
+ end
+end
diff --git a/modules/github_integration/db/migrate/20240501093751_create_deploy_status_checks.rb b/modules/github_integration/db/migrate/20240501093751_create_deploy_status_checks.rb
new file mode 100644
index 000000000000..2881a758cdeb
--- /dev/null
+++ b/modules/github_integration/db/migrate/20240501093751_create_deploy_status_checks.rb
@@ -0,0 +1,12 @@
+class CreateDeployStatusChecks < ActiveRecord::Migration[7.1]
+ def change
+ create_table :deploy_status_checks do |t|
+ t.references :deploy_target
+ t.references :github_pull_request
+
+ t.text :core_sha, null: false
+
+ t.timestamps
+ end
+ end
+end
diff --git a/modules/github_integration/db/migrate/20240502081436_add_merge_commit_sha_to_github_pull_requests.rb b/modules/github_integration/db/migrate/20240502081436_add_merge_commit_sha_to_github_pull_requests.rb
new file mode 100644
index 000000000000..5ae78152b886
--- /dev/null
+++ b/modules/github_integration/db/migrate/20240502081436_add_merge_commit_sha_to_github_pull_requests.rb
@@ -0,0 +1,5 @@
+class AddMergeCommitShaToGithubPullRequests < ActiveRecord::Migration[7.1]
+ def change
+ add_column :github_pull_requests, :merge_commit_sha, :text
+ end
+end
diff --git a/modules/github_integration/frontend/module/pull-request/pull-request-state.component.sass b/modules/github_integration/frontend/module/pull-request/pull-request-state.component.sass
index 80af28bde1dd..dc0c8a9933b3 100644
--- a/modules/github_integration/frontend/module/pull-request/pull-request-state.component.sass
+++ b/modules/github_integration/frontend/module/pull-request/pull-request-state.component.sass
@@ -49,3 +49,6 @@
&_closed
background-color: #d73a49
+
+ &_deployed
+ background-color: #d73af9
diff --git a/modules/github_integration/frontend/module/pull-request/pull-request-state.component.ts b/modules/github_integration/frontend/module/pull-request/pull-request-state.component.ts
index 387a2dc378d1..33bbec81afca 100644
--- a/modules/github_integration/frontend/module/pull-request/pull-request-state.component.ts
+++ b/modules/github_integration/frontend/module/pull-request/pull-request-state.component.ts
@@ -35,7 +35,7 @@ import {
import { PathHelperService } from 'core-app/core/path-helper/path-helper.service';
import { I18nService } from 'core-app/core/i18n/i18n.service';
-export type PullRequestState = 'opened'|'closed'|'referenced'|'ready_for_review'|'merged'|'draft';
+export type PullRequestState = 'opened'|'closed'|'referenced'|'ready_for_review'|'merged'|'draft'|'deployed';
@Component({
selector: 'op-github-pull-request-state',
diff --git a/modules/github_integration/frontend/module/pull-request/pull-request.component.ts b/modules/github_integration/frontend/module/pull-request/pull-request.component.ts
index ecc70c8ec87a..5b81b1e8e202 100644
--- a/modules/github_integration/frontend/module/pull-request/pull-request.component.ts
+++ b/modules/github_integration/frontend/module/pull-request/pull-request.component.ts
@@ -71,6 +71,9 @@ export class PullRequestComponent {
if (this.pullRequest.state === 'open') {
return (this.pullRequest.draft ? 'draft' : 'open');
}
+ if (this.pullRequest.state === 'deployed') {
+ return 'deployed';
+ }
return (this.pullRequest.merged ? 'merged' : 'closed');
}
diff --git a/modules/github_integration/frontend/module/tab-header/styles/tab-header.sass b/modules/github_integration/frontend/module/tab-header/styles/tab-header.sass
index 0f80e7171fe4..3f87eb6aec16 100644
--- a/modules/github_integration/frontend/module/tab-header/styles/tab-header.sass
+++ b/modules/github_integration/frontend/module/tab-header/styles/tab-header.sass
@@ -27,14 +27,6 @@
*/
.github-pr-header
- display: flex
- flex-wrap: wrap-reverse
- justify-content: flex-end
-
- border-bottom: 1px solid #ddd
-
- margin: 0 0 0.8rem 0
-
.title
flex: 1 1 auto
border-bottom: 0
diff --git a/modules/github_integration/frontend/module/tab-header/tab-header.template.html b/modules/github_integration/frontend/module/tab-header/tab-header.template.html
index 82a240172f72..a26ea6faee58 100644
--- a/modules/github_integration/frontend/module/tab-header/tab-header.template.html
+++ b/modules/github_integration/frontend/module/tab-header/tab-header.template.html
@@ -1,4 +1,4 @@
-
+
{{text.title}}
diff --git a/modules/github_integration/frontend/module/tab-prs/tab-prs.component.html b/modules/github_integration/frontend/module/tab-prs/tab-prs.component.html
index 1ad3aa9b9cd6..e8c9e37e551a 100644
--- a/modules/github_integration/frontend/module/tab-prs/tab-prs.component.html
+++ b/modules/github_integration/frontend/module/tab-prs/tab-prs.component.html
@@ -1,5 +1,8 @@
-
+
{ OpenProject::FeatureDecisions.deploy_targets_active? } # can only be enable at start-time
end
+
+ menu :admin_menu,
+ :deploy_targets,
+ { controller: "/deploy_targets", action: "index" },
+ if: ->(*) { OpenProject::FeatureDecisions.deploy_targets_active? && User.current.admin? },
+ parent: :admin_github_integration,
+ caption: :label_deploy_target_plural,
+ icon: "hosting"
end
initializer "github.register_hook" do
@@ -62,6 +92,13 @@ class Engine < ::Rails::Engine
end
end
+ extend_api_response(:v3, :root) do
+ property :core_sha,
+ exec_context: :decorator,
+ getter: ->(*) { OpenProject::VERSION.core_sha },
+ if: ->(*) { current_user.admin? || current_user.allowed_globally?(:introspection) }
+ end
+
extend_api_response(:v3, :work_packages, :work_package,
&::OpenProject::GithubIntegration::Patches::API::WorkPackageRepresenter.extension)
@@ -86,12 +123,24 @@ class Engine < ::Rails::Engine
end
add_cron_jobs do
- {
+ jobs = {
"Cron::ClearOldPullRequestsJob": {
cron: "25 1 * * *", # runs at 1:25 nightly
class: ::Cron::ClearOldPullRequestsJob.name
}
}
+
+ # Enabling the feature flag at runtime won't enable
+ # the cron job. So if you want this feature, enable it
+ # at start-time.
+ if OpenProject::FeatureDecisions.deploy_targets_active?
+ jobs["Cron::CheckDeployStatusJob"] = {
+ cron: "15,45 * * * *", # runs every half hour
+ class: ::Cron::CheckDeployStatusJob.name
+ }
+ end
+
+ jobs
end
end
end
diff --git a/modules/github_integration/lib/open_project/github_integration/services/upsert_pull_request.rb b/modules/github_integration/lib/open_project/github_integration/services/upsert_pull_request.rb
index 2ed0ea027f78..914af5b921b2 100644
--- a/modules/github_integration/lib/open_project/github_integration/services/upsert_pull_request.rb
+++ b/modules/github_integration/lib/open_project/github_integration/services/upsert_pull_request.rb
@@ -70,6 +70,7 @@ def extract_params(payload)
.fetch("repo")
.fetch("html_url"),
draft: payload.fetch("draft"),
+ merge_commit_sha: payload["merge_commit_sha"],
merged: payload.fetch("merged"),
merged_by: github_user_id(payload["merged_by"]),
merged_at: payload["merged_at"],
diff --git a/modules/github_integration/spec/factories/deploy_status_check_factory.rb b/modules/github_integration/spec/factories/deploy_status_check_factory.rb
new file mode 100644
index 000000000000..2bc91787f426
--- /dev/null
+++ b/modules/github_integration/spec/factories/deploy_status_check_factory.rb
@@ -0,0 +1,34 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2012-2024 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+FactoryBot.define do
+ factory :deploy_status_check do
+ deploy_target
+ github_pull_request
+ end
+end
diff --git a/modules/github_integration/spec/factories/deploy_target_factory.rb b/modules/github_integration/spec/factories/deploy_target_factory.rb
new file mode 100644
index 000000000000..42fcf21bd5eb
--- /dev/null
+++ b/modules/github_integration/spec/factories/deploy_target_factory.rb
@@ -0,0 +1,37 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2012-2024 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+FactoryBot.define do
+ factory :deploy_target do
+ type { "OpenProject" }
+
+ sequence(:host) { |n| "https://qa-#{n}.openproject-edge.com" }
+
+ api_key { "4p1k3y" }
+ end
+end
diff --git a/modules/github_integration/spec/lib/open_project/github_integration/notification_handler/pull_request_spec.rb b/modules/github_integration/spec/lib/open_project/github_integration/notification_handler/pull_request_spec.rb
index 289fad06664b..8cb4edab8d78 100644
--- a/modules/github_integration/spec/lib/open_project/github_integration/notification_handler/pull_request_spec.rb
+++ b/modules/github_integration/spec/lib/open_project/github_integration/notification_handler/pull_request_spec.rb
@@ -51,6 +51,7 @@
"merged" => pr_merged,
"merged_by" => nil,
"merged_at" => nil,
+ "merge_commit_sha" => nil,
"comments" => 1,
"review_comments" => 2,
"additions" => 3,
diff --git a/modules/github_integration/spec/lib/open_project/github_integration/services/upsert_pull_request_spec.rb b/modules/github_integration/spec/lib/open_project/github_integration/services/upsert_pull_request_spec.rb
index afc97f1b655c..b504f87e2536 100644
--- a/modules/github_integration/spec/lib/open_project/github_integration/services/upsert_pull_request_spec.rb
+++ b/modules/github_integration/spec/lib/open_project/github_integration/services/upsert_pull_request_spec.rb
@@ -181,7 +181,8 @@
{
"merged" => true,
"merged_by" => user_payload,
- "merged_at" => "20210410T09:45:03Z"
+ "merged_at" => "20210410T09:45:03Z",
+ "merge_commit_sha" => "955af2f83de81c39fcf912376855eb3ee5e38f26"
}
end
@@ -195,7 +196,8 @@
github_user:,
merged: true,
merged_by: github_user,
- merged_at: Time.zone.parse("20210410T09:45:03Z")
+ merged_at: Time.zone.parse("20210410T09:45:03Z"),
+ merge_commit_sha: "955af2f83de81c39fcf912376855eb3ee5e38f26"
)
end
end
diff --git a/modules/github_integration/spec/requests/extended_root_resource_spec.rb b/modules/github_integration/spec/requests/extended_root_resource_spec.rb
new file mode 100644
index 000000000000..03422d4e26e7
--- /dev/null
+++ b/modules/github_integration/spec/requests/extended_root_resource_spec.rb
@@ -0,0 +1,90 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2012-2024 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+require "spec_helper"
+require "rack/test"
+
+RSpec.describe "API v3 Root resource with the github integration extension", with_flag: { deploy_targets: true } do
+ include Rack::Test::Methods
+ include API::V3::Utilities::PathHelper
+
+ let(:current_user) do
+ create(:user, member_with_roles: { project => role })
+ end
+ let(:role) { create(:project_role, permissions: []) }
+ let(:project) { create(:project, public: false) }
+
+ before do
+ # reset permissions cache, otherwise the introspection permissions enabled with the
+ # deploy_targets feature flag won't be registered
+ OpenProject::AccessControl.instance_variable_set(:@permissions, nil)
+ end
+
+ describe "#get" do
+ let(:response) { last_response }
+ let(:get_path) { api_v3_paths.root }
+
+ subject { response.body }
+
+ context "without introspection permission" do
+ before do
+ allow(User).to receive(:current).and_return(current_user)
+
+ get get_path
+ end
+
+ it "responds with 200" do
+ expect(response.status).to eq(200) # rubocop:disable RSpecRails/HaveHttpStatus
+ end
+
+ it "does not include the core SHA in the res" do
+ expect(subject).not_to have_json_path("coreSha")
+ end
+ end
+
+ context "with introspection permission" do
+ let(:current_user) { create(:user, global_permissions: [:introspection]) }
+ let(:core_sha) { "b86f391bf02c345e934ca8a945d83fc82d2063ef" }
+
+ before do
+ allow(OpenProject::VERSION).to receive(:core_sha).and_return core_sha
+ allow(User).to receive(:current).and_return(current_user)
+
+ get get_path
+ end
+
+ it "responds with 200" do
+ expect(response.status).to eq(200) # rubocop:disable RSpecRails/HaveHttpStatus
+ end
+
+ it "does includes the core SHA in the response" do
+ expect(subject).to be_json_eql(core_sha.to_json).at_path("coreSha")
+ end
+ end
+ end
+end
diff --git a/modules/github_integration/spec/workers/cron/check_deploy_status_job_spec.rb b/modules/github_integration/spec/workers/cron/check_deploy_status_job_spec.rb
new file mode 100644
index 000000000000..5de8a3f4be78
--- /dev/null
+++ b/modules/github_integration/spec/workers/cron/check_deploy_status_job_spec.rb
@@ -0,0 +1,115 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2012-2024 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+require "spec_helper"
+
+RSpec.describe Cron::CheckDeployStatusJob, type: :job, with_flag: { deploy_targets: true } do
+ let(:api_key) { "foobar42" }
+
+ let(:merge_commit_sha) { "576e25f7befffa5fc02a4311704e9894a5c9bdd4" }
+ let(:core_sha) { "663f3a128aef9c0b031cbd59bb6f740ee50130a7" }
+
+ let(:work_package) { create(:work_package) }
+
+ let(:deploy_target) { create(:deploy_target, api_key:) }
+ let(:pull_request) { create(:github_pull_request, work_packages: [work_package], state: :closed, merge_commit_sha:) }
+
+ let(:job) { described_class.new }
+
+ context "with no prior checks and the same deployed sha" do
+ before do
+ deploy_target
+ pull_request
+
+ allow(job).to receive(:openproject_core_sha).with(deploy_target.host, api_key).and_return(core_sha)
+ allow(job).to receive(:commit_contains?).with(core_sha, merge_commit_sha).and_return true
+
+ job.perform
+ end
+
+ it "marks the pull request 'deployed'" do
+ expect(pull_request.reload.state).to eq "deployed"
+ end
+ end
+
+ context "with prior checks" do
+ before do
+ allow(job).to receive(:openproject_core_sha).with(deploy_target.host, api_key).and_return(core_sha)
+ allow(job).to receive :commit_contains?
+ end
+
+ context "with the same core sha" do
+ let!(:deploy_status_check) { create(:deploy_status_check, deploy_target:, github_pull_request: pull_request, core_sha:) }
+
+ before do
+ job.perform
+ end
+
+ it "leaves the pull request closed while not checking with github again" do
+ expect(pull_request.reload.state).to eq "closed"
+ expect(job).not_to have_received :commit_contains?
+ end
+ end
+
+ context "with a different core sha in the previous check" do
+ let!(:deploy_status_check) do
+ create(:deploy_status_check, deploy_target:, github_pull_request: pull_request, core_sha: "foo")
+ end
+
+ before do
+ allow(job).to receive(:commit_contains?).with(core_sha, merge_commit_sha).and_return contains_commit
+
+ job.perform
+ end
+
+ context "with the same core sha deployed" do
+ let(:contains_commit) { true }
+
+ it "marks the pull request deployed" do
+ expect(pull_request.reload.state).to eq "deployed"
+ end
+
+ it "has checked with github again" do
+ expect(job).to have_received(:commit_contains?).with(core_sha, merge_commit_sha)
+ end
+ end
+
+ context "with a different core sha deployed" do
+ let(:contains_commit) { false }
+
+ it "leaves the pull request closed" do
+ expect(pull_request.reload.state).to eq "closed"
+ end
+
+ it "has checked with github again" do
+ expect(job).to have_received(:commit_contains?).with(core_sha, merge_commit_sha)
+ end
+ end
+ end
+ end
+end
diff --git a/modules/gitlab_integration/frontend/module/tab-header-issue/styles/tab-header-issue.sass b/modules/gitlab_integration/frontend/module/tab-header-issue/styles/tab-header-issue.sass
index e5eb014b830a..7e42b26b2fc5 100644
--- a/modules/gitlab_integration/frontend/module/tab-header-issue/styles/tab-header-issue.sass
+++ b/modules/gitlab_integration/frontend/module/tab-header-issue/styles/tab-header-issue.sass
@@ -28,13 +28,6 @@
//++
.gitlab-issue-header
- display: flex
- flex-wrap: wrap-reverse
- justify-content: flex-end
-
- border-bottom: 1px solid #ddd
- background-color: var(--body-background)
-
.title
flex: 1 1 auto
border-bottom: 0
diff --git a/modules/gitlab_integration/frontend/module/tab-header-issue/tab-header-issue.template.html b/modules/gitlab_integration/frontend/module/tab-header-issue/tab-header-issue.template.html
index 1fc5efe1023f..b3b8936dd350 100644
--- a/modules/gitlab_integration/frontend/module/tab-header-issue/tab-header-issue.template.html
+++ b/modules/gitlab_integration/frontend/module/tab-header-issue/tab-header-issue.template.html
@@ -1,4 +1,4 @@
-
diff --git a/modules/storages/app/workers/storages/health_status_mailer_job.rb b/modules/storages/app/workers/storages/health_status_mailer_job.rb
index d765e8746104..01b3ba5df0ae 100644
--- a/modules/storages/app/workers/storages/health_status_mailer_job.rb
+++ b/modules/storages/app/workers/storages/health_status_mailer_job.rb
@@ -50,7 +50,7 @@ def perform(storage:)
return if storage.health_healthy?
admin_users.each do |admin|
- ::Storages::StoragesMailer.notify_unhealthy(admin, storage).deliver_later
+ StoragesMailer.notify_unhealthy(admin, storage).deliver_later
end
HealthStatusMailerJob.schedule(storage:)
diff --git a/modules/storages/spec/features/storages/admin/create_storage_spec.rb b/modules/storages/spec/features/storages/admin/create_storage_spec.rb
index 08434f5cd136..620e1a3eee7e 100644
--- a/modules/storages/spec/features/storages/admin/create_storage_spec.rb
+++ b/modules/storages/spec/features/storages/admin/create_storage_spec.rb
@@ -50,8 +50,8 @@
expect(page).to be_axe_clean.within "#content"
- within(".PageHeader-titleBar") do
- click_on("Storage")
+ within(".SubHeader") do
+ page.find_test_selector("storages-create-new-provider-button").click
within_test_selector("storages-select-provider-action-menu") { click_on("Nextcloud") }
end
@@ -193,8 +193,8 @@
it "renders enterprise icon and redirects to upsale", :webmock do
visit admin_settings_storages_path
- within(".PageHeader-titleBar") do
- click_on("Storage")
+ within(".SubHeader") do
+ page.find_test_selector("storages-create-new-provider-button").click
within_test_selector("storages-select-provider-action-menu") do
expect(page).to have_css(".octicon-op-enterprise-addons")
@@ -213,9 +213,8 @@
expect(page).to be_axe_clean.within "#content"
- within(".PageHeader-titleBar") do
- click_on("Storage")
-
+ within(".SubHeader") do
+ page.find_test_selector("storages-create-new-provider-button").click
within_test_selector("storages-select-provider-action-menu") { click_on("OneDrive/SharePoint") }
end
diff --git a/modules/webhooks/config/locales/crowdin/no.yml b/modules/webhooks/config/locales/crowdin/no.yml
index 796eb300644c..47bc3bb3c2fe 100644
--- a/modules/webhooks/config/locales/crowdin/no.yml
+++ b/modules/webhooks/config/locales/crowdin/no.yml
@@ -5,14 +5,14 @@
activerecord:
attributes:
webhooks/webhook:
- url: 'Nyttelast URL'
- secret: 'Hemmelig signatur'
+ url: 'Nyttelast-URL'
+ secret: 'Hemmelig signaturnøkkel'
events: 'Hendelser'
projects: 'Aktiverte prosjekter'
webhooks/log:
event_name: 'Navn på hendelse'
- url: 'Nyttelast URL'
- response_code: 'Svar kode'
+ url: 'Nyttelast-URL'
+ response_code: 'Svarkode'
response_body: 'Svar'
models:
webhooks/outgoing_webhook: "Utgående webhook"
@@ -21,26 +21,26 @@
plural: Webhooks
resources:
time_entry:
- name: "Tid oppføring"
+ name: "Timeføring"
outgoing:
no_results_table: Ingen webhooks har blitt definert ennå.
label_add_new: Legg til ny webhook
label_edit: Rediger webhook
- label_event_resources: Event ressurser
+ label_event_resources: Hendelsesressurser
events:
created: "Opprettet"
updated: "Oppdatert"
explanation:
text: >
- Ved forekomst av en hendelse som oppretting av en arbeidspakke eller en oppdatering fra et prosjekt, OpenProject vil sende en POST-forespørsel til de konfigurerte nettendepunktene. Ofte blir arrangementet sendt etter at %{link} er godkjent.
+ Ved forekomst av en hendelse som oppretting av en arbeidspakke eller en oppdatering fra et prosjekt, vil OpenProject sende en POST-forespørsel til de konfigurerte nettendepunktene. Ofte blir hendelsen sendt etter at %{link} er godkjent.
link: konfigurert summeringsperiode
status:
- enabled: 'Webhooks aktivert'
- disabled: 'Webhooks er deaktivert'
- enabled_text: 'webhooken sender ut nyttelaster for de definerte hendelsene nedenfor.'
+ enabled: 'Webhook er aktivert'
+ disabled: 'Webhook er deaktivert'
+ enabled_text: 'Webhooken sender ut nyttelaster for de definerte hendelsene nedenfor.'
disabled_text: 'Klikk på rediger-knappen for å aktivere webhook.'
deliveries:
- no_results_table: Ingen leveranser er gjennomført for dette webhooket de siste dagene.
+ no_results_table: Ingen leveranser er gjennomført for denne webhooken de siste dagene.
title: 'Nylige leveranser'
time: 'Tid for levering'
form:
@@ -51,7 +51,7 @@
placeholder: 'Valgfri beskrivelse for webhook.'
enabled:
description: >
- Når merket av, vil webhook utløse på de valgte hendelsene. Fjern avmerkingen for å deaktivere webhook.
+ Når merket av, vil webhooken utløses for de valgte hendelsene. Fjern merkingen for å deaktivere webhooken.
events:
title: 'Aktiverte hendelser'
project_ids:
@@ -63,4 +63,4 @@
title: 'Valgte prosjekter'
secret:
description: >
- Hvis angitt, brukes denne hemmelige verdien av OpenProject for å signere webhook nyttelasten.
+ Hvis angitt, brukes denne hemmelige verdien av OpenProject for å signere webhook-nyttelasten.
diff --git a/packaging/addons/openproject/bin/postinstall b/packaging/addons/openproject/bin/postinstall
index 403f26a16ac2..7192cf54dc93 100755
--- a/packaging/addons/openproject/bin/postinstall
+++ b/packaging/addons/openproject/bin/postinstall
@@ -10,6 +10,11 @@ CLI="${APP_NAME}"
${CLI} config:set OPENPROJECT_SEED_ADMIN_USER_MAIL="$(wiz_get "openproject/admin_email" || wiz_get "smtp/admin_email")"
${CLI} config:set RECOMPILE_RAILS_ASSETS="true"
+# Convert language pt to pt-BR (work packages #53374 and #55318)
+if [ "$(wiz_get "openproject/default_language")" = "pt" ]; then
+ wiz_set "openproject/default_language" "pt-BR"
+fi
+
# Set the configured default language
# Will be unset at installation postinstall before restart to ensure the setting is writable
${CLI} config:set OPENPROJECT_DEFAULT_LANGUAGE="$(wiz_get "openproject/default_language" || echo "en")"
diff --git a/script/github_pr_errors b/script/github_pr_errors
index 4a7741037169..44c8fd7747fc 100755
--- a/script/github_pr_errors
+++ b/script/github_pr_errors
@@ -10,6 +10,7 @@ require "optparse"
require "base64"
require "pathname"
require "pry"
+require "time"
require "yaml"
require "httpx"
@@ -274,6 +275,7 @@ class Report
:head_branch,
:head_sha,
:commit_message,
+ :run_started_at,
:merge_branch_sha
end
@@ -283,7 +285,7 @@ end
# rubocop:disable Layout/LineLength
# Looks like this in the job log:
-# Process 28: TEST_ENV_NUMBER=28 RUBYOPT=-I/usr/local/bundle/bundler/gems/turbo_tests-3148ae6c3482/lib -r/usr/local/bundle/gems/bundler-2.5.10/lib/bundler/setup -W0 RSPEC_SILENCE_FILTER_ANNOUNCEMENTS=1 /usr/local/bundle/gems/bundler-2.5.10/exe/bundle exec rspec --seed 52674 --format TurboTests::JsonRowsFormatter --out tmp/test-pipes/subprocess-28 --format ParallelTests::RSpec::RuntimeLogger --out spec/support/turbo_runtime_features.log spec/features/api_docs/index_spec.rb spec/features/custom_fields/reorder_options_spec.rb spec/features/projects/projects_portfolio_spec.rb spec/features/projects/template_spec.rb spec/features/versions/edit_spec.rb spec/features/work_packages/details/markdown/description_editor_spec.rb spec/features/work_packages/table/hierarchy/hierarchy_parent_below_spec.rb spec/features/work_packages/table/inline_create/inline_create_refresh_spec.rb spec/features/work_packages/table/invalid_query_spec.rb spec/features/work_packages/tabs/activity_revisions_spec.rb
+# Process 28: TEST_ENV_NUMBER=28 RUBYOPT=-I/usr/local/bundle/bundler/gems/turbo_tests-3148ae6c3482/lib -r/usr/local/bundle/gems/bundler-2.5.11/lib/bundler/setup -W0 RSPEC_SILENCE_FILTER_ANNOUNCEMENTS=1 /usr/local/bundle/gems/bundler-2.5.11/exe/bundle exec rspec --seed 52674 --format TurboTests::JsonRowsFormatter --out tmp/test-pipes/subprocess-28 --format ParallelTests::RSpec::RuntimeLogger --out spec/support/turbo_runtime_features.log spec/features/api_docs/index_spec.rb spec/features/custom_fields/reorder_options_spec.rb spec/features/projects/projects_portfolio_spec.rb spec/features/projects/template_spec.rb spec/features/versions/edit_spec.rb spec/features/work_packages/details/markdown/description_editor_spec.rb spec/features/work_packages/table/hierarchy/hierarchy_parent_below_spec.rb spec/features/work_packages/table/inline_create/inline_create_refresh_spec.rb spec/features/work_packages/table/invalid_query_spec.rb spec/features/work_packages/tabs/activity_revisions_spec.rb
# rubocop:enable Layout/LineLength
class TestsGroup
attr_accessor :test_env_number, :seed, :files
@@ -453,9 +455,11 @@ class Formatter
report.head_branch = workflow_run["head_branch"]
report.head_sha = workflow_run["head_sha"]
report.commit_message = commit_message(workflow_run)
+ report.run_started_at = Time.parse(workflow_run["run_started_at"]).utc
warn " Branch: #{report.head_branch.bold}"
warn " Commit SHA: #{report.head_sha.bold}"
warn " Commit message: #{report.commit_message.bold}"
+ warn " Run started at: #{report.run_started_at.localtime.to_s.bold}"
display_pull_request_info(workflow_run)
end
diff --git a/spec/contracts/settings/working_days_and_hours_params_contract_spec.rb b/spec/contracts/settings/working_days_and_hours_params_contract_spec.rb
new file mode 100644
index 000000000000..37fe7cdd54e9
--- /dev/null
+++ b/spec/contracts/settings/working_days_and_hours_params_contract_spec.rb
@@ -0,0 +1,120 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2012-2024 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+require "spec_helper"
+require "contracts/shared/model_contract_shared_context"
+
+RSpec.describe Settings::WorkingDaysAndHoursParamsContract do
+ include_context "ModelContract shared context"
+ shared_let(:current_user) { create(:admin) }
+ let(:setting) { Setting }
+ let(:params) { { working_days: [1], hours_per_day: 8, days_per_week: 5, days_per_month: 20 } }
+ let(:contract) do
+ described_class.new(setting, current_user, params:)
+ end
+
+ it_behaves_like "contract is valid for active admins and invalid for regular users"
+
+ %i[working_days hours_per_day days_per_week days_per_month].each do |attribute|
+ context "without #{attribute}" do
+ let(:params) { { working_days: [1], hours_per_day: 8, days_per_week: 5, days_per_month: 20 }.except(attribute) }
+
+ include_examples "contract is invalid", base: :"#{attribute}_are_missing"
+ end
+ end
+
+ context "with an ApplyWorkingDaysChangeJob already existing",
+ with_good_job: WorkPackages::ApplyWorkingDaysChangeJob do
+ let(:params) { { working_days: [1, 2, 3], hours_per_day: 8, days_per_week: 5, days_per_month: 20 } }
+
+ before do
+ WorkPackages::ApplyWorkingDaysChangeJob
+ .set(wait: 10.minutes) # GoodJob executes inline job without wait immediately
+ .perform_later(user_id: current_user.id,
+ previous_non_working_days: [],
+ previous_working_days: [1, 2, 3, 4])
+ end
+
+ include_examples "contract is invalid", base: :previous_working_day_changes_unprocessed
+ end
+
+ context "when days_per_week and days_per_month aren't consistent with each other" do
+ # There are 4 weeks per month on average, so 10 days per month in non-sensical given 5 days per week
+ let(:params) { { working_days: [1], hours_per_day: 8, days_per_week: 5, days_per_month: 10 } }
+
+ include_examples "contract is invalid", base: :days_per_week_and_days_per_month_are_inconsistent
+ end
+
+ describe "0 durations" do
+ context "when hours_per_day is 0" do
+ let(:params) { { working_days: [1], hours_per_day: 0, days_per_week: 5, days_per_month: 20 } }
+
+ include_examples "contract is invalid", base: :durations_are_not_positive_numbers
+ end
+
+ # These two are correlated. Making only one of them 0 will also
+ # add the "incosistent" error tested for above.
+ context "when days_per_week or days_per_month is 0" do
+ let(:params) { { working_days: [1], hours_per_day: 8, days_per_week: 0, days_per_month: 0 } }
+
+ include_examples "contract is invalid", base: :durations_are_not_positive_numbers
+ end
+
+ context "when all durations are 0" do
+ let(:params) { { working_days: [1], hours_per_day: 0, days_per_week: 0, days_per_month: 0 } }
+
+ include_examples "contract is invalid", base: :durations_are_not_positive_numbers
+ end
+ end
+
+ describe "Text durations" do
+ let(:params) { { working_days: [1], hours_per_day: "blah", days_per_week: "5", days_per_month: "20" } }
+
+ include_examples "contract is invalid", base: :durations_are_not_positive_numbers
+ end
+
+ describe "Negative durations" do
+ let(:params) { { working_days: [1], hours_per_day: -2, days_per_week: -5, days_per_month: -20 } }
+
+ include_examples "contract is invalid", base: :durations_are_not_positive_numbers
+ end
+
+ describe "Out-of-bounds durations" do
+ context "when hours_per_day is greater than 24" do
+ let(:params) { { working_days: [1], hours_per_day: 25, days_per_week: 5, days_per_month: 20 } }
+
+ include_examples "contract is invalid", base: :hours_per_day_is_out_of_bounds
+ end
+
+ context "when days_per_week is greater than 7 and days_per_month is greater than 31" do
+ let(:params) { { working_days: [1], hours_per_day: 8, days_per_week: 8, days_per_month: 32 } }
+
+ include_examples "contract is invalid", base: %i[days_per_week_is_out_of_bounds days_per_month_is_out_of_bounds]
+ end
+ end
+end
diff --git a/spec/controllers/admin/settings/work_packages_settings_controller_spec.rb b/spec/controllers/admin/settings/work_packages_settings_controller_spec.rb
index 93d9a06c2824..0f162cd8b9f9 100644
--- a/spec/controllers/admin/settings/work_packages_settings_controller_spec.rb
+++ b/spec/controllers/admin/settings/work_packages_settings_controller_spec.rb
@@ -54,7 +54,7 @@
}
}
expect(Setting.work_package_done_ratio).to eq("status")
- expect(WorkPackages::Progress::ApplyStatusesPCompleteJob)
+ expect(WorkPackages::Progress::ApplyStatusesChangeJob)
.to have_been_enqueued.with(cause_type: "progress_mode_changed_to_status_based")
perform_enqueued_jobs
@@ -76,7 +76,7 @@
work_package_done_ratio: "status"
}
}
- expect(WorkPackages::Progress::ApplyStatusesPCompleteJob)
+ expect(WorkPackages::Progress::ApplyStatusesChangeJob)
.not_to have_been_enqueued
end
end
@@ -93,7 +93,7 @@
work_package_done_ratio: "field"
}
}
- expect(WorkPackages::Progress::ApplyStatusesPCompleteJob)
+ expect(WorkPackages::Progress::ApplyStatusesChangeJob)
.not_to have_been_enqueued
end
end
diff --git a/spec/controllers/admin/settings/working_days_settings_controller_spec.rb b/spec/controllers/admin/settings/working_days_and_hours_settings_controller_spec.rb
similarity index 86%
rename from spec/controllers/admin/settings/working_days_settings_controller_spec.rb
rename to spec/controllers/admin/settings/working_days_and_hours_settings_controller_spec.rb
index 8063cf1fd809..38e753137e99 100644
--- a/spec/controllers/admin/settings/working_days_settings_controller_spec.rb
+++ b/spec/controllers/admin/settings/working_days_and_hours_settings_controller_spec.rb
@@ -28,18 +28,21 @@
require "spec_helper"
-RSpec.describe Admin::Settings::WorkingDaysSettingsController do
+RSpec.describe Admin::Settings::WorkingDaysAndHoursSettingsController do
shared_let(:user) { create(:admin) }
current_user { user }
- require_admin_and_render_template("working_days_settings")
+ require_admin_and_render_template("working_days_and_hours_settings")
describe "update" do
let(:working_days) { [*"1".."7"] }
let(:non_working_days_attributes) { {} }
+ let(:hours_per_day) { 4 }
+ let(:days_per_week) { 5 }
+ let(:days_per_month) { 20 }
let(:params) do
- { settings: { working_days:, non_working_days_attributes: } }
+ { settings: { working_days:, non_working_days_attributes:, hours_per_day:, days_per_week:, days_per_month: } }
end
subject { patch "update", params: }
@@ -91,7 +94,8 @@
expect(assigns(:modified_non_working_days)).to contain_exactly(
hash_including("name" => "Christmas Eve", "date" => "2022-12-24"),
hash_including("name" => "Christmas Eve2", "date" => "2022-12-24"),
- hash_including(nwd_to_delete.as_json(only: %i[id name date]).merge("_destroy" => true))
+ hash_including(nwd_to_delete.as_json(only: %i[id name
+ date]).merge("_destroy" => true))
)
end
diff --git a/spec/controllers/statuses_controller_spec.rb b/spec/controllers/statuses_controller_spec.rb
index da8e941e2c8e..a4058d23a443 100644
--- a/spec/controllers/statuses_controller_spec.rb
+++ b/spec/controllers/statuses_controller_spec.rb
@@ -143,9 +143,48 @@
it "does not start any jobs to update work packages % complete values" do
expect(status.reload).to have_attributes(default_done_ratio: new_default_done_ratio)
- expect(WorkPackages::Progress::ApplyStatusesPCompleteJob)
+ expect(WorkPackages::Progress::ApplyStatusesChangeJob)
.not_to have_been_enqueued
end
+
+ context "when also marking a status as excluded from totals calculations" do
+ before_all do
+ status.update_columns(name: "Rejected",
+ default_done_ratio: 70)
+ end
+
+ shared_let(:status_new) { create(:status, name: "New", default_done_ratio: "0") }
+ shared_let_work_packages(<<~TABLE)
+ hierarchy | status | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete
+ parent | New | | | | 20h | 15h | 25%
+ child | Rejected | 10h | 5h | 50% | | |
+ other child | New | 10h | 10h | 0% | | |
+ TABLE
+
+ let(:status_params) do
+ { default_done_ratio: new_default_done_ratio,
+ excluded_from_totals: true }
+ end
+
+ it "starts a job to update totals of work packages having excluded children" do
+ expect(status.reload).to have_attributes(excluded_from_totals: true)
+ expect(WorkPackages::Progress::ApplyStatusesChangeJob)
+ .to have_been_enqueued.with(cause_type: "status_changed",
+ status_name: status.name,
+ status_id: status.id,
+ changes: { "excluded_from_totals" => [false, true] })
+
+ perform_enqueued_jobs
+
+ expect_work_packages([parent, child, other_child], <<~TABLE)
+ subject | status | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete
+ parent | New | | | | 10h | 10h | 0%
+ child | Rejected | 10h | 5h | 50% | | |
+ other child | New | 10h | 10h | 0% | | |
+ TABLE
+ expect(parent.last_journal.details["cause"].last).to include("type" => "status_changed")
+ end
+ end
end
context "when in status-based mode",
@@ -158,16 +197,16 @@
it "starts a job to update work packages % complete values" do
old_default_done_ratio = status.default_done_ratio
expect(status.reload).to have_attributes(default_done_ratio: new_default_done_ratio)
- expect(WorkPackages::Progress::ApplyStatusesPCompleteJob)
- .to have_been_enqueued.with(cause_type: "status_p_complete_changed",
+ expect(WorkPackages::Progress::ApplyStatusesChangeJob)
+ .to have_been_enqueued.with(cause_type: "status_changed",
status_name: status.name,
status_id: status.id,
- change: [old_default_done_ratio, new_default_done_ratio])
+ changes: { "default_done_ratio" => [old_default_done_ratio, new_default_done_ratio] })
perform_enqueued_jobs
expect(work_package.reload.read_attribute(:done_ratio)).to eq(new_default_done_ratio)
- expect(work_package.last_journal.details["cause"].last).to include("type" => "status_p_complete_changed")
+ expect(work_package.last_journal.details["cause"].last).to include("type" => "status_changed")
end
end
@@ -175,16 +214,84 @@
let(:status_params) { { default_done_ratio: status.default_done_ratio } }
it "does not start any jobs" do
- expect(WorkPackages::Progress::ApplyStatusesPCompleteJob)
+ expect(WorkPackages::Progress::ApplyStatusesChangeJob)
.not_to have_been_enqueued
end
end
- context "when changing something else than the default % complete" do
+ context "when marking a status as excluded from totals calculations" do
+ before_all do
+ status.update_columns(name: "Rejected",
+ default_done_ratio: 70)
+ end
+
+ shared_let(:status_new) { create(:status, name: "New", default_done_ratio: "0") }
+ shared_let_work_packages(<<~TABLE)
+ hierarchy | status | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete
+ parent | New | | | 0% | 20h | 16h | 20%
+ child | Rejected | 10h | 3h | 70% | | |
+ other child | New | 10h | 10h | 0% | | |
+ TABLE
+
+ let(:status_params) { { excluded_from_totals: true } }
+
+ it "starts a job to update totals of work packages having excluded children" do
+ expect(status.reload).to have_attributes(excluded_from_totals: true)
+ expect(WorkPackages::Progress::ApplyStatusesChangeJob)
+ .to have_been_enqueued.with(cause_type: "status_changed",
+ status_name: status.name,
+ status_id: status.id,
+ changes: { "excluded_from_totals" => [false, true] })
+
+ perform_enqueued_jobs
+
+ expect_work_packages([parent, child, other_child], <<~TABLE)
+ subject | status | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete
+ parent | New | | | 0% | 10h | 10h | 0%
+ child | Rejected | 10h | 3h | 70% | | |
+ other child | New | 10h | 10h | 0% | | |
+ TABLE
+ expect(parent.last_journal.details["cause"].last).to include("type" => "status_changed")
+ end
+
+ context "when also changing the default % complete of the status" do
+ let(:new_default_done_ratio) { 40 }
+ let(:status_params) { { excluded_from_totals: true, default_done_ratio: new_default_done_ratio } }
+
+ it "starts a job to update both total values and % complete of work packages" do
+ old_default_done_ratio = status.default_done_ratio
+ expect(status.reload).to have_attributes(default_done_ratio: new_default_done_ratio,
+ excluded_from_totals: true)
+ expect(WorkPackages::Progress::ApplyStatusesChangeJob)
+ .to have_been_enqueued.with(cause_type: "status_changed",
+ status_name: status.name,
+ status_id: status.id,
+ changes: { "default_done_ratio" => [old_default_done_ratio, new_default_done_ratio],
+ "excluded_from_totals" => [false, true] })
+
+ perform_enqueued_jobs
+
+ expect_work_packages([parent, child, other_child], <<~TABLE)
+ subject | status | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete
+ parent | New | | | 0% | 10h | 10h | 0%
+ child | Rejected | 10h | 6h | 40% | | |
+ other child | New | 10h | 10h | 0% | | |
+ TABLE
+
+ [parent, child].each do |work_package|
+ expect(work_package.journals.count).to eq(2)
+ expect(work_package.last_journal.details["cause"].last).to include("type" => "status_changed")
+ end
+ expect(other_child.journals.count).to eq(1) # this one should not have changed
+ end
+ end
+ end
+
+ context "when changing something else than default % complete or exclude from totals" do
let(:status_params) { { name: "Another status name" } }
it "does not start any jobs" do
- expect(WorkPackages::Progress::ApplyStatusesPCompleteJob)
+ expect(WorkPackages::Progress::ApplyStatusesChangeJob)
.not_to have_been_enqueued
end
end
diff --git a/spec/factories/status_factory.rb b/spec/factories/status_factory.rb
index ddaba8fc5872..586a9082c566 100644
--- a/spec/factories/status_factory.rb
+++ b/spec/factories/status_factory.rb
@@ -31,11 +31,21 @@
sequence(:name) { |n| "status #{n}" }
is_closed { false }
is_readonly { false }
+ excluded_from_totals { false }
+
+ trait :excluded_from_totals do
+ excluded_from_totals { true }
+ end
factory :closed_status do
is_closed { true }
end
+ factory :rejected_status do
+ excluded_from_totals
+ name { "Rejected" }
+ end
+
factory :default_status do
is_default { true }
end
diff --git a/spec/features/activities/work_package_activity_spec.rb b/spec/features/activities/work_package_activity_spec.rb
index 7604f302926e..3eab179c7920 100644
--- a/spec/features/activities/work_package_activity_spec.rb
+++ b/spec/features/activities/work_package_activity_spec.rb
@@ -58,13 +58,13 @@
wp_page.expect_and_dismiss_toaster(message: "Successful update.")
end
- it "displays changed attributes in the activity tab" do
+ it "displays changed attributes in the activity tab", :aggregate_failures do
within("activity-entry", text: admin.name) do
expect(page).to have_list_item(text: "% Complete set to 50%")
- expect(page).to have_list_item(text: "Work set to 10.00")
- expect(page).to have_list_item(text: "Remaining work set to 5.00")
- expect(page).to have_list_item(text: "Total work set to 20.00")
- expect(page).to have_list_item(text: "Total remaining work set to 8.00")
+ expect(page).to have_list_item(text: "Work set to 1d 2h")
+ expect(page).to have_list_item(text: "Remaining work set to 5h")
+ expect(page).to have_list_item(text: "Total work set to 2d 4h")
+ expect(page).to have_list_item(text: "Total remaining work set to 1d")
expect(page).to have_list_item(text: "Total % complete set to 60%")
end
end
diff --git a/spec/features/admin/project_custom_fields/project_mappings_spec.rb b/spec/features/admin/project_custom_fields/project_mappings_spec.rb
index 2491b114c14a..93f226dd3f5f 100644
--- a/spec/features/admin/project_custom_fields/project_mappings_spec.rb
+++ b/spec/features/admin/project_custom_fields/project_mappings_spec.rb
@@ -82,6 +82,24 @@
end
end
+ it "allows to link a project" do
+ project = create(:project)
+ subproject = create(:project, parent: project)
+ click_on "Add projects"
+
+ within_test_selector("settings--new-project-custom-field-mapping-component") do
+ autocompleter = page.find(".op-project-autocompleter")
+ autocompleter.fill_in with: project.name
+ find(".ng-option-label", text: project.name).click
+ check "Include sub-projects"
+
+ click_on "Add"
+ end
+
+ expect(page).to have_text(project.name)
+ expect(page).to have_text(subproject.name)
+ end
+
context "and the project custom field is required" do
shared_let(:project_custom_field) { create(:project_custom_field, is_required: true) }
diff --git a/spec/features/admin/working_days_spec.rb b/spec/features/admin/working_days_spec.rb
index 23c605c5f76e..516f5900b1f0 100644
--- a/spec/features/admin/working_days_spec.rb
+++ b/spec/features/admin/working_days_spec.rb
@@ -47,7 +47,7 @@
current_user { admin }
before do
- visit admin_settings_working_days_path
+ visit admin_settings_working_days_and_hours_path
end
describe "week days" do
@@ -284,7 +284,7 @@ def working_days_setting
# rubocop:disable RSpec/AnyInstance
allow_any_instance_of(NonWorkingDay)
.to receive(:errors)
- .and_return(errors)
+ .and_return(errors)
# rubocop:enable RSpec/AnyInstance
delete_button = page.first(".op-non-working-days-list--delete-icon .icon-delete", visible: :all)
diff --git a/spec/features/notifications/reminder_mail_spec.rb b/spec/features/notifications/reminder_mail_spec.rb
index d2e8dbde9f04..aa7eb9f0aa8e 100644
--- a/spec/features/notifications/reminder_mail_spec.rb
+++ b/spec/features/notifications/reminder_mail_spec.rb
@@ -2,13 +2,13 @@
require_relative "../users/notifications/shared_examples"
RSpec.describe "Reminder email sending", js: false do
- let!(:project) { create(:project, members: { current_user => role }) }
- let!(:mute_project) { create(:project, members: { current_user => role }) }
+ let!(:project) { create(:project, members: { receiving_user => role }) }
+ let!(:mute_project) { create(:project, members: { receiving_user => role }) }
let(:role) { create(:project_role, permissions: %i[view_work_packages]) }
let(:other_user) { create(:user) }
let(:work_package) { create(:work_package, project:) }
- let(:watched_work_package) { create(:work_package, project:, watcher_users: [current_user]) }
- let(:involved_work_package) { create(:work_package, project:, assigned_to: current_user) }
+ let(:watched_work_package) { create(:work_package, project:, watcher_users: [receiving_user]) }
+ let(:involved_work_package) { create(:work_package, project:, assigned_to: receiving_user) }
# GoodJob::Job#cron_at is used for scheduling the reminder mails.
# It needs to be within a time frame eligible for sending out mails for the chosen
# time zone. For the time zone Hawaii (UTC-10) this means 8:00:00 as the job has a cron tab to be run every 15 min.
@@ -27,13 +27,7 @@
# between the changes to a work package and the reminder mail being sent out.
let(:work_package_update_time) { ActiveSupport::TimeZone["Pacific/Honolulu"].parse("2021-09-30T01:50:34").utc }
- around do |example|
- Timecop.travel(work_package_update_time) do
- example.run
- end
- end
-
- current_user do
+ let!(:receiving_user) do
create(
:user,
preferences: {
@@ -61,25 +55,29 @@
)
end
- before do
- watched_work_package
- work_package
- involved_work_package
+ around do |example|
+ Timecop.travel(work_package_update_time) do
+ example.run
+ end
+ end
+ before do
ActiveJob::Base.disable_test_adapter
-
- scheduled_job
end
it "sends a digest mail based on the configuration", with_settings: { journal_aggregation_time_minutes: 0 } do
# Perform some actions the user listens to
User.execute_as other_user do
+ watched_work_package
+ work_package
+ involved_work_package
+
note = <<~NOTE
Hey
- @#{current_user.name}
+ data-text="@#{receiving_user.name}">
+ @#{receiving_user.name}
NOTE
@@ -93,10 +91,15 @@
involved_work_package.save!
end
- 2.times { GoodJob.perform_inline }
+ GoodJob.perform_inline
+ scheduled_job
+ GoodJob.perform_inline
expect(ActionMailer::Base.deliveries.length).to be 1
+ # 3 work package created
+ # 3 times updated (1 for each work package)
+ # One of those was a mention for which the user opted out to not receive immediate notifications
expect(ActionMailer::Base.deliveries.first.subject)
- .to eql "OpenProject - 1 unread notification including a mention"
+ .to eql "OpenProject - 6 unread notifications including a mention"
end
end
diff --git a/spec/features/types/form_configuration_spec.rb b/spec/features/types/form_configuration_spec.rb
index 2b8c93a0a32c..fd4751c28241 100644
--- a/spec/features/types/form_configuration_spec.rb
+++ b/spec/features/types/form_configuration_spec.rb
@@ -227,7 +227,7 @@
wp_page.expect_group("Estimates and progress") do
wp_page.expect_attributes estimated_time: "-"
- wp_page.expect_attributes spent_time: "0 h"
+ wp_page.expect_attributes spent_time: "0h"
end
# New work package has the same configuration
diff --git a/spec/features/work_packages/display_fields/spent_time_display_spec.rb b/spec/features/work_packages/display_fields/spent_time_display_spec.rb
index ed7da8592b33..e5db5620d112 100644
--- a/spec/features/work_packages/display_fields/spent_time_display_spec.rb
+++ b/spec/features/work_packages/display_fields/spent_time_display_spec.rb
@@ -85,7 +85,7 @@ def log_time_via_modal(user_field_visible: true, log_for_user: nil, date: Time.z
end.to change(TimeEntry, :count).by(1)
# the value is updated automatically
- spent_time_field.expect_display_value "1 h"
+ spent_time_field.expect_display_value "1h"
TimeEntry.last.tap do |te|
expect(te.work_package).to eq(work_package)
@@ -112,7 +112,7 @@ def log_time_via_modal(user_field_visible: true, log_for_user: nil, date: Time.z
log_time_via_modal log_for_user: other_user
# the value is updated automatically
- spent_time_field.expect_display_value "1 h"
+ spent_time_field.expect_display_value "1h"
time_entry = TimeEntry.last
expect(time_entry.user).to eq other_user
@@ -128,7 +128,7 @@ def log_time_via_modal(user_field_visible: true, log_for_user: nil, date: Time.z
log_time_via_modal
# the value is updated automatically
- spent_time_field.expect_display_value "1 h"
+ spent_time_field.expect_display_value "1h"
end
context "with a user with non-one unit numbers", with_settings: { available_languages: %w[en ja] } do
@@ -145,7 +145,7 @@ def log_time_via_modal(user_field_visible: true, log_for_user: nil, date: Time.z
log_time_via_modal
# the value is updated automatically
- spent_time_field.expect_display_value "1 h"
+ spent_time_field.expect_display_value "1h"
end
end
end
@@ -164,7 +164,7 @@ def log_time_via_modal(user_field_visible: true, log_for_user: nil, date: Time.z
it "shows no logging button within the display field" do
spent_time_field.time_log_icon_visible false
- spent_time_field.expect_display_value "0 h"
+ spent_time_field.expect_display_value "0h"
end
end
@@ -188,7 +188,7 @@ def log_time_via_modal(user_field_visible: true, log_for_user: nil, date: Time.z
log_time_via_modal user_field_visible: false
# the value is updated automatically
- spent_time_field.expect_display_value "1 h"
+ spent_time_field.expect_display_value "1h"
end
end
@@ -213,8 +213,8 @@ def log_time_via_modal(user_field_visible: true, log_for_user: nil, date: Time.z
log_time_via_modal
- expect(page).to have_css("tr:nth-of-type(1) .wp-table--cell-td.spentTime", text: "1 h")
- expect(page).to have_css("tr:nth-of-type(2) .wp-table--cell-td.spentTime", text: "0 h")
+ expect(page).to have_css("tr:nth-of-type(1) .wp-table--cell-td.spentTime", text: "1h")
+ expect(page).to have_css("tr:nth-of-type(2) .wp-table--cell-td.spentTime", text: "0h")
end
end
end
diff --git a/spec/features/work_packages/display_fields/work_display_spec.rb b/spec/features/work_packages/display_fields/work_display_spec.rb
index 2770e732fb37..ddfee0c921b0 100644
--- a/spec/features/work_packages/display_fields/work_display_spec.rb
+++ b/spec/features/work_packages/display_fields/work_display_spec.rb
@@ -91,7 +91,7 @@
child | 3h |
TABLE
- include_examples "work display", expected_text: "1 h·Σ 4 h"
+ include_examples "work display", expected_text: "1h·Σ 4h"
end
context "with just work" do
@@ -101,7 +101,7 @@
child | 0h |
TABLE
- include_examples "work display", expected_text: "1 h"
+ include_examples "work display", expected_text: "1h"
end
context "with just total work with (parent work 0 h)" do
@@ -111,7 +111,7 @@
child | 3h |
TABLE
- include_examples "work display", expected_text: "0 h·Σ 3 h"
+ include_examples "work display", expected_text: "0h·Σ 3h"
end
context "with just total work (parent work unset)" do
@@ -121,7 +121,7 @@
child | 3h |
TABLE
- include_examples "work display", expected_text: "-·Σ 3 h"
+ include_examples "work display", expected_text: "-·Σ 3h"
end
context "with neither work nor total work (both 0 h)" do
@@ -131,7 +131,7 @@
child | 0h |
TABLE
- include_examples "work display", expected_text: "0 h"
+ include_examples "work display", expected_text: "0h"
end
context "with just total work being 0h" do
@@ -141,7 +141,7 @@
child | 0h |
TABLE
- include_examples "work display", expected_text: "-·Σ 0 h"
+ include_examples "work display", expected_text: "-·Σ 0h"
end
context "with neither work nor total work (both unset)" do
@@ -172,11 +172,11 @@
wp_table.visit_query query
# parent
- expect(page).to have_content("5 h·Σ 20 h")
- expect(page).to have_link("Σ 20 h")
+ expect(page).to have_content("5h·Σ 2d 4h")
+ expect(page).to have_link("Σ 2d 4h")
# child 2
- expect(page).to have_content("3 h·Σ 15 h")
- expect(page).to have_link("Σ 15 h")
+ expect(page).to have_content("3h·Σ 1d 7h")
+ expect(page).to have_link("Σ 1d 7h")
end
context "when clicking the link of a top parent" do
@@ -185,7 +185,7 @@
end
it "shows a work package table with a parent filter to list the direct children" do
- click_on("Σ 20 h")
+ click_on("Σ 2d 4h")
wp_table.expect_work_package_count(4)
wp_table.expect_work_package_listed(parent, child1, child2, child3)
@@ -202,8 +202,8 @@
end
it "shows also all ancestors in the work package table" do
- expect(page).to have_content("Work\n3 h·Σ 15 h")
- click_on("Σ 15 h")
+ expect(page).to have_content("Work\n3h·Σ 1d 7h")
+ click_on("Σ 1d 7h")
wp_table.expect_work_package_count(3)
wp_table.expect_work_package_listed(parent, child2, grand_child21)
diff --git a/spec/features/work_packages/edit_work_package_spec.rb b/spec/features/work_packages/edit_work_package_spec.rb
index 8e38c7247872..07d5d8bf2e47 100644
--- a/spec/features/work_packages/edit_work_package_spec.rb
+++ b/spec/features/work_packages/edit_work_package_spec.rb
@@ -143,8 +143,8 @@ def visit!
responsible: manager.name,
assignee: manager.name,
combinedDate: "03/04/2013 - 03/20/2013",
- estimatedTime: "10 h",
- remainingTime: "7 h",
+ estimatedTime: "1d 2h",
+ remainingTime: "7h",
percentageDone: "30%",
subject: "a new subject",
description: "a new description",
diff --git a/spec/features/work_packages/index_sums_spec.rb b/spec/features/work_packages/index_sums_spec.rb
index 5c894d85da34..896ea730cb85 100644
--- a/spec/features/work_packages/index_sums_spec.rb
+++ b/spec/features/work_packages/index_sums_spec.rb
@@ -144,14 +144,16 @@
wp_table.expect_work_package_listed work_package1, work_package2
# Expect the total sums row
- within(:row, "Total sum") do |row|
- expect(row).to have_css(".estimatedTime", text: "25 h")
- expect(row).to have_css(".remainingTime", text: "12.5 h")
- expect(row).to have_css(".#{int_cf.attribute_name(:camel_case)}", text: "12")
- expect(row).to have_css(".#{float_cf.attribute_name(:camel_case)}", text: "13.2")
- expect(row).to have_css(".laborCosts", text: "15.00 EUR")
- expect(row).to have_css(".materialCosts", text: "7.50 EUR") # Unit costs
- expect(row).to have_css(".overallCosts", text: "22.50 EUR")
+ aggregate_failures do
+ within(:row, "Total sum") do |row|
+ expect(row).to have_css(".estimatedTime", text: "3d 1h")
+ expect(row).to have_css(".remainingTime", text: "1d 4h 30m")
+ expect(row).to have_css(".#{int_cf.attribute_name(:camel_case)}", text: "12")
+ expect(row).to have_css(".#{float_cf.attribute_name(:camel_case)}", text: "13.2")
+ expect(row).to have_css(".laborCosts", text: "15.00 EUR")
+ expect(row).to have_css(".materialCosts", text: "7.50 EUR") # Unit costs
+ expect(row).to have_css(".overallCosts", text: "22.50 EUR")
+ end
end
# Update the sum
@@ -160,14 +162,16 @@
wp_table.edit_field(work_package1, :remainingTime)
.update "12"
- within(:row, "Total sum") do |row|
- expect(row).to have_css(".estimatedTime", text: "35 h")
- expect(row).to have_css(".remainingTime", text: "19.5 h")
- expect(row).to have_css(".#{int_cf.attribute_name(:camel_case)}", text: "12")
- expect(row).to have_css(".#{float_cf.attribute_name(:camel_case)}", text: "13.2")
- expect(row).to have_css(".laborCosts", text: "15.00 EUR")
- expect(row).to have_css(".materialCosts", text: "7.50 EUR") # Unit costs
- expect(row).to have_css(".overallCosts", text: "22.50 EUR")
+ aggregate_failures do
+ within(:row, "Total sum") do |row|
+ expect(row).to have_css(".estimatedTime", text: "4d 3h")
+ expect(row).to have_css(".remainingTime", text: "2d 3h 30m")
+ expect(row).to have_css(".#{int_cf.attribute_name(:camel_case)}", text: "12")
+ expect(row).to have_css(".#{float_cf.attribute_name(:camel_case)}", text: "13.2")
+ expect(row).to have_css(".laborCosts", text: "15.00 EUR")
+ expect(row).to have_css(".materialCosts", text: "7.50 EUR") # Unit costs
+ expect(row).to have_css(".overallCosts", text: "22.50 EUR")
+ end
end
# Enable groups
@@ -179,32 +183,38 @@
first_sum_row, second_sum_row = *find_all(:row, "Sum")
# First status row
- expect(first_sum_row).to have_css(".estimatedTime", text: "20 h")
- expect(first_sum_row).to have_css(".remainingTime", text: "12 h")
- expect(first_sum_row).to have_css(".#{int_cf.attribute_name(:camel_case)}", text: "5")
- expect(first_sum_row).to have_css(".#{float_cf.attribute_name(:camel_case)}", text: "5.5")
- expect(first_sum_row).to have_css(".laborCosts", text: "15.00 EUR")
- expect(first_sum_row).to have_css(".materialCosts", text: "7.50 EUR") # Unit costs
- expect(first_sum_row).to have_css(".overallCosts", text: "22.50 EUR")
+ aggregate_failures do
+ expect(first_sum_row).to have_css(".estimatedTime", text: "2d 4h")
+ expect(first_sum_row).to have_css(".remainingTime", text: "1d 4h")
+ expect(first_sum_row).to have_css(".#{int_cf.attribute_name(:camel_case)}", text: "5")
+ expect(first_sum_row).to have_css(".#{float_cf.attribute_name(:camel_case)}", text: "5.5")
+ expect(first_sum_row).to have_css(".laborCosts", text: "15.00 EUR")
+ expect(first_sum_row).to have_css(".materialCosts", text: "7.50 EUR") # Unit costs
+ expect(first_sum_row).to have_css(".overallCosts", text: "22.50 EUR")
+ end
# Second status row
- expect(second_sum_row).to have_css(".estimatedTime", text: "15 h")
- expect(second_sum_row).to have_css(".remainingTime", text: "7.5 h")
- expect(second_sum_row).to have_css(".#{int_cf.attribute_name(:camel_case)}", text: "7")
- expect(second_sum_row).to have_css(".#{float_cf.attribute_name(:camel_case)}", text: "7.7")
- expect(second_sum_row).to have_css(".laborCosts", text: "", exact_text: true)
- expect(second_sum_row).to have_css(".materialCosts", text: "", exact_text: true) # Unit costs
- expect(second_sum_row).to have_css(".overallCosts", text: "", exact_text: true)
+ aggregate_failures do
+ expect(second_sum_row).to have_css(".estimatedTime", text: "1d 7h")
+ expect(second_sum_row).to have_css(".remainingTime", text: "7h 30m")
+ expect(second_sum_row).to have_css(".#{int_cf.attribute_name(:camel_case)}", text: "7")
+ expect(second_sum_row).to have_css(".#{float_cf.attribute_name(:camel_case)}", text: "7.7")
+ expect(second_sum_row).to have_css(".laborCosts", text: "", exact_text: true)
+ expect(second_sum_row).to have_css(".materialCosts", text: "", exact_text: true) # Unit costs
+ expect(second_sum_row).to have_css(".overallCosts", text: "", exact_text: true)
+ end
# Total sums row is unchanged
- within(:row, "Total sum") do |row|
- expect(row).to have_css(".estimatedTime", text: "35 h")
- expect(row).to have_css(".remainingTime", text: "19.5 h")
- expect(row).to have_css(".#{int_cf.attribute_name(:camel_case)}", text: "12")
- expect(row).to have_css(".#{float_cf.attribute_name(:camel_case)}", text: "13.2")
- expect(row).to have_css(".laborCosts", text: "15.00 EUR")
- expect(row).to have_css(".materialCosts", text: "7.50 EUR") # Unit costs
- expect(row).to have_css(".overallCosts", text: "22.50 EUR")
+ aggregate_failures do
+ within(:row, "Total sum") do |row|
+ expect(row).to have_css(".estimatedTime", text: "4d 3h")
+ expect(row).to have_css(".remainingTime", text: "2d 3h 30m")
+ expect(row).to have_css(".#{int_cf.attribute_name(:camel_case)}", text: "12")
+ expect(row).to have_css(".#{float_cf.attribute_name(:camel_case)}", text: "13.2")
+ expect(row).to have_css(".laborCosts", text: "15.00 EUR")
+ expect(row).to have_css(".materialCosts", text: "7.50 EUR") # Unit costs
+ expect(row).to have_css(".overallCosts", text: "22.50 EUR")
+ end
end
# Collapsing groups will also hide the sums row
@@ -270,14 +280,16 @@
wp_table.expect_work_package_listed work_package1, work_package2, work_package3, work_package4
# Expect the total sums row without filtering
- within(:row, "Total sum") do |row|
- expect(row).to have_css(".estimatedTime", text: "50 h")
- expect(row).to have_css(".remainingTime", text: "25 h")
- expect(row).to have_css(".#{int_cf.attribute_name(:camel_case)}", text: "24")
- expect(row).to have_css(".#{float_cf.attribute_name(:camel_case)}", text: "26.4")
- expect(row).to have_css(".laborCosts", text: "40.00 EUR")
- expect(row).to have_css(".materialCosts", text: "18.00 EUR") # Unit costs
- expect(row).to have_css(".overallCosts", text: "58.00 EUR")
+ aggregate_failures do
+ within(:row, "Total sum") do |row|
+ expect(row).to have_css(".estimatedTime", text: "1w 1d 2h")
+ expect(row).to have_css(".remainingTime", text: "3d 1h")
+ expect(row).to have_css(".#{int_cf.attribute_name(:camel_case)}", text: "24")
+ expect(row).to have_css(".#{float_cf.attribute_name(:camel_case)}", text: "26.4")
+ expect(row).to have_css(".laborCosts", text: "40.00 EUR")
+ expect(row).to have_css(".materialCosts", text: "18.00 EUR") # Unit costs
+ expect(row).to have_css(".overallCosts", text: "58.00 EUR")
+ end
end
# Filter
@@ -289,14 +301,16 @@
expect(page).to have_row("WorkPackage", count: 2) # works because the subject name includes "WorkPackage"
# Expect the total sums row to have changed
- within(:row, "Total sum") do |row|
- expect(row).to have_css(".estimatedTime", text: "30 h")
- expect(row).to have_css(".remainingTime", text: "15 h")
- expect(row).to have_css(".#{int_cf.attribute_name(:camel_case)}", text: "14")
- expect(row).to have_css(".#{float_cf.attribute_name(:camel_case)}", text: "15.4")
- expect(row).to have_css(".laborCosts", text: "", exact_text: true)
- expect(row).to have_css(".materialCosts", text: "", exact_text: true) # Unit costs
- expect(row).to have_css(".overallCosts", text: "", exact_text: true)
+ aggregate_failures do
+ within(:row, "Total sum") do |row|
+ expect(row).to have_css(".estimatedTime", text: "3d 6h")
+ expect(row).to have_css(".remainingTime", text: "1d 7h")
+ expect(row).to have_css(".#{int_cf.attribute_name(:camel_case)}", text: "14")
+ expect(row).to have_css(".#{float_cf.attribute_name(:camel_case)}", text: "15.4")
+ expect(row).to have_css(".laborCosts", text: "", exact_text: true)
+ expect(row).to have_css(".materialCosts", text: "", exact_text: true) # Unit costs
+ expect(row).to have_css(".overallCosts", text: "", exact_text: true)
+ end
end
# Filter by status open
@@ -313,32 +327,38 @@
first_sum_row, second_sum_row = *find_all(:row, "Sum")
# First status row
- expect(first_sum_row).to have_css(".estimatedTime", text: "10 h")
- expect(first_sum_row).to have_css(".remainingTime", text: "5 h")
- expect(first_sum_row).to have_css(".#{int_cf.attribute_name(:camel_case)}", text: "5")
- expect(first_sum_row).to have_css(".#{float_cf.attribute_name(:camel_case)}", text: "5.5")
- expect(first_sum_row).to have_css(".laborCosts", text: "15.00 EUR")
- expect(first_sum_row).to have_css(".materialCosts", text: "7.50 EUR") # Unit costs
- expect(first_sum_row).to have_css(".overallCosts", text: "22.50 EUR")
+ aggregate_failures do
+ expect(first_sum_row).to have_css(".estimatedTime", text: "1d 2h")
+ expect(first_sum_row).to have_css(".remainingTime", text: "5h")
+ expect(first_sum_row).to have_css(".#{int_cf.attribute_name(:camel_case)}", text: "5")
+ expect(first_sum_row).to have_css(".#{float_cf.attribute_name(:camel_case)}", text: "5.5")
+ expect(first_sum_row).to have_css(".laborCosts", text: "15.00 EUR")
+ expect(first_sum_row).to have_css(".materialCosts", text: "7.50 EUR") # Unit costs
+ expect(first_sum_row).to have_css(".overallCosts", text: "22.50 EUR")
+ end
# Second status row
- expect(second_sum_row).to have_css(".estimatedTime", text: "15 h")
- expect(second_sum_row).to have_css(".remainingTime", text: "7.5 h")
- expect(second_sum_row).to have_css(".#{int_cf.attribute_name(:camel_case)}", text: "7")
- expect(second_sum_row).to have_css(".#{float_cf.attribute_name(:camel_case)}", text: "7.7")
- expect(second_sum_row).to have_css(".laborCosts", text: "", exact_text: true)
- expect(second_sum_row).to have_css(".materialCosts", text: "", exact_text: true) # Unit costs
- expect(second_sum_row).to have_css(".overallCosts", text: "", exact_text: true)
+ aggregate_failures do
+ expect(second_sum_row).to have_css(".estimatedTime", text: "1d 7h")
+ expect(second_sum_row).to have_css(".remainingTime", text: "7h 30m")
+ expect(second_sum_row).to have_css(".#{int_cf.attribute_name(:camel_case)}", text: "7")
+ expect(second_sum_row).to have_css(".#{float_cf.attribute_name(:camel_case)}", text: "7.7")
+ expect(second_sum_row).to have_css(".laborCosts", text: "", exact_text: true)
+ expect(second_sum_row).to have_css(".materialCosts", text: "", exact_text: true) # Unit costs
+ expect(second_sum_row).to have_css(".overallCosts", text: "", exact_text: true)
+ end
# Total sum
- within(:row, "Total sum") do |row|
- expect(row).to have_css(".estimatedTime", text: "25 h")
- expect(row).to have_css(".remainingTime", text: "12.5 h")
- expect(row).to have_css(".#{int_cf.attribute_name(:camel_case)}", text: "12")
- expect(row).to have_css(".#{float_cf.attribute_name(:camel_case)}", text: "13.2")
- expect(row).to have_css(".laborCosts", text: "15.00 EUR")
- expect(row).to have_css(".materialCosts", text: "7.50 EUR") # Unit costs
- expect(row).to have_css(".overallCosts", text: "22.50 EUR")
+ aggregate_failures do
+ within(:row, "Total sum") do |row|
+ expect(row).to have_css(".estimatedTime", text: "3d 1h")
+ expect(row).to have_css(".remainingTime", text: "1d 4h 30m")
+ expect(row).to have_css(".#{int_cf.attribute_name(:camel_case)}", text: "12")
+ expect(row).to have_css(".#{float_cf.attribute_name(:camel_case)}", text: "13.2")
+ expect(row).to have_css(".laborCosts", text: "15.00 EUR")
+ expect(row).to have_css(".materialCosts", text: "7.50 EUR") # Unit costs
+ expect(row).to have_css(".overallCosts", text: "22.50 EUR")
+ end
end
end
end
diff --git a/spec/features/work_packages/progress_modal_spec.rb b/spec/features/work_packages/progress_modal_spec.rb
index fee8996468c3..f1fb3f7ce36f 100644
--- a/spec/features/work_packages/progress_modal_spec.rb
+++ b/spec/features/work_packages/progress_modal_spec.rb
@@ -340,8 +340,7 @@ def update_work_package_with(work_package, attributes)
context "with all values set" do
before { update_work_package_with(work_package, estimated_hours: 10.0, remaining_hours: 2.12345) }
- it "populates fields with correctly values formatted " \
- "with the minimum fractional part if present, and 2 decimals max" do
+ it "populates fields with correctly values formatted" do
work_package_table.visit_query(progress_query)
work_package_table.expect_work_package_listed(work_package)
@@ -351,8 +350,8 @@ def update_work_package_with(work_package, attributes)
work_edit_field.activate!
- work_edit_field.expect_modal_field_value("10")
- remaining_work_edit_field.expect_modal_field_value("2.12")
+ work_edit_field.expect_modal_field_value("1d 2h")
+ remaining_work_edit_field.expect_modal_field_value("2h 7m")
percent_complete_edit_field.expect_modal_field_value("78", readonly: true)
end
end
@@ -365,7 +364,7 @@ def update_work_package_with(work_package, attributes)
work_package.save(validate: false)
end
- it "does not lose precision due to conversion from ISO duration to hours" do
+ it "does not lose precision due to conversion from ISO duration to hours (rounded to closest minute)" do
work_package_table.visit_query(progress_query)
work_package_table.expect_work_package_listed(work_package)
@@ -382,10 +381,11 @@ def update_work_package_with(work_package, attributes)
expect(work_package.estimated_hours).to eq(2.56)
expect(work_package.remaining_hours).to eq(0.28)
- # work should be displayed as 2.56, and remaining work as 0.28
+ # work should be displayed as "2h 34m" ("2h 33m 36s" rounded to minutes),
+ # and remaining work as "17m" ("16m 48s" rounded to minutes)
work_edit_field.activate!
- work_edit_field.expect_modal_field_value("2.56")
- remaining_work_edit_field.expect_modal_field_value("0.28")
+ work_edit_field.expect_modal_field_value("2h 34m")
+ remaining_work_edit_field.expect_modal_field_value("17m")
end
end
@@ -522,7 +522,7 @@ def update_work_package_with(work_package, attributes)
specify "Case 2: when work is set to 12h, " \
"remaining work is automatically set to 6h " \
"and subsequently work is set to 14h, " \
- "remaining work updates to 8h" do
+ "remaining work updates to 1d" do
work_package_table.visit_query(progress_query)
work_package_table.expect_work_package_listed(work_package)
@@ -534,11 +534,11 @@ def update_work_package_with(work_package, attributes)
work_edit_field.set_value("12")
page.driver.wait_for_network_idle # Wait for live-update to finish
- remaining_work_edit_field.expect_modal_field_value("6")
+ remaining_work_edit_field.expect_modal_field_value("6h")
work_edit_field.set_value("14")
page.driver.wait_for_network_idle # Wait for live-update to finish
- remaining_work_edit_field.expect_modal_field_value("8")
+ remaining_work_edit_field.expect_modal_field_value("1d")
end
specify "Case 3: when work is set to 2h, " \
@@ -556,11 +556,11 @@ def update_work_package_with(work_package, attributes)
work_edit_field.set_value("2")
page.driver.wait_for_network_idle # Wait for live-update to finish
- remaining_work_edit_field.expect_modal_field_value("0")
+ remaining_work_edit_field.expect_modal_field_value("0h")
work_edit_field.set_value("12")
page.driver.wait_for_network_idle # Wait for live-update to finish
- remaining_work_edit_field.expect_modal_field_value("6")
+ remaining_work_edit_field.expect_modal_field_value("6h")
end
end
end
diff --git a/spec/features/work_packages/remaining_time_spec.rb b/spec/features/work_packages/remaining_time_spec.rb
index 7d253396f69b..599d999fec3f 100644
--- a/spec/features/work_packages/remaining_time_spec.rb
+++ b/spec/features/work_packages/remaining_time_spec.rb
@@ -50,7 +50,7 @@
# need to update work first to enable the remaining work field
wp_page.update_attributes estimatedTime: "200" # rubocop:disable Rails/ActiveRecordAliases
wp_page.update_attributes remainingTime: "125" # rubocop:disable Rails/ActiveRecordAliases
- wp_page.expect_attributes remainingTime: "125 h"
+ wp_page.expect_attributes remainingTime: "3w 5h"
work_package.reload
expect(work_package.remaining_hours).to eq 125.0
@@ -70,8 +70,8 @@
# need to update work first to enable the remaining work field
wp_table_page.update_work_package_attributes work_package, estimatedTime: "200"
wp_table_page.update_work_package_attributes work_package, remainingTime: "125"
- wp_table_page.expect_work_package_with_attributes work_package, remainingTime: "125 h"
- wp_table_page.expect_sums_row_with_attributes remainingTime: "125 h"
+ wp_table_page.expect_work_package_with_attributes work_package, remainingTime: "3w 5h"
+ wp_table_page.expect_sums_row_with_attributes remainingTime: "3w 5h"
work_package.reload
expect(work_package.remaining_hours).to eq 125.0
diff --git a/spec/lib/api/v3/statuses/status_representer_spec.rb b/spec/lib/api/v3/statuses/status_representer_spec.rb
index 799a822cc116..e704992c0710 100644
--- a/spec/lib/api/v3/statuses/status_representer_spec.rb
+++ b/spec/lib/api/v3/statuses/status_representer_spec.rb
@@ -30,9 +30,9 @@
RSpec.describe API::V3::Statuses::StatusRepresenter do
let(:status) { build_stubbed(:status) }
- let(:representer) { described_class.new(status, current_user: double("current_user")) }
+ let(:representer) { described_class.new(status, current_user: instance_double(User)) }
- context "generation" do
+ describe "generation" do
subject(:generated) { representer.to_json }
it { is_expected.to include_json("Status".to_json).at_path("_type") }
@@ -43,6 +43,7 @@
it { is_expected.to have_json_path("isClosed") }
it { is_expected.to have_json_path("isDefault") }
it { is_expected.to have_json_path("isReadonly") }
+ it { is_expected.to have_json_path("excludedFromTotals") }
it { is_expected.to have_json_path("position") }
it { is_expected.to have_json_path("defaultDoneRatio") }
@@ -52,6 +53,7 @@
it { is_expected.to be_json_eql(status.is_closed.to_json).at_path("isClosed") }
it { is_expected.to be_json_eql(status.is_default.to_json).at_path("isDefault") }
it { is_expected.to be_json_eql(status.is_readonly.to_json).at_path("isReadonly") }
+ it { is_expected.to be_json_eql(status.excluded_from_totals.to_json).at_path("excludedFromTotals") }
it { is_expected.to be_json_eql(status.position.to_json).at_path("position") }
it {
@@ -74,12 +76,15 @@
describe "caching" do
it "is based on the representer's cache_key" do
- expect(OpenProject::Cache)
+ allow(OpenProject::Cache)
.to receive(:fetch)
- .with(representer.json_cache_key)
.and_call_original
representer.to_json
+
+ expect(OpenProject::Cache)
+ .to have_received(:fetch)
+ .with(representer.json_cache_key)
end
describe "#json_cache_key" do
@@ -98,7 +103,7 @@
end
it "changes when the status is updated" do
- status.updated_at = Time.now + 20.seconds
+ status.updated_at = 20.seconds.from_now
expect(representer.json_cache_key)
.not_to eql former_cache_key
diff --git a/spec/lib/journal_formatter/cause_spec.rb b/spec/lib/journal_formatter/cause_spec.rb
index f85369703a05..1729d4e0b254 100644
--- a/spec/lib/journal_formatter/cause_spec.rb
+++ b/spec/lib/journal_formatter/cause_spec.rb
@@ -36,14 +36,15 @@
shared_let(:work_package) { create(:work_package) }
let(:instance) { described_class.new(build(:work_package_journal)) }
- let(:link) do
+ let(:work_package_html_link) do
link_to_work_package(work_package, all_link: true)
end
+ let(:work_package_raw_link) { "##{work_package.id}" }
# we need to tell the url_helper that there is not controller to get url_options so that we can call link_to
let(:controller) { nil }
- subject do
+ def render(cause, html:)
if Journal::VALID_CAUSE_TYPES.exclude?(cause["type"])
raise "#{cause['type'].inspect} is not a valid cause type from Journal::VALID_CAUSE_TYPES. " \
"Please use one of #{Journal::VALID_CAUSE_TYPES}"
@@ -52,197 +53,211 @@
instance.render("cause", [nil, cause], html:)
end
+ RSpec::Matchers.define :render_html_variant do |expected|
+ match do |cause|
+ @cause = cause
+ @actual = render(cause, html: true)
+ values_match? expected, @actual
+ end
+
+ description do
+ "render HTML variant with #{surface_descriptions_in(expected).inspect}"
+ end
+
+ failure_message do |actual|
+ "expected #{@cause} to render HTML variant as expected\n " \
+ "expected: #{surface_descriptions_in(expected).inspect}\n " \
+ "actual: #{actual.inspect}"
+ end
+ end
+
+ RSpec::Matchers.define :render_raw_variant do |expected|
+ match do |cause|
+ @cause = cause
+ @actual = render(cause, html: false)
+ values_match? expected, @actual
+ end
+
+ description do
+ "render raw text variant with #{surface_descriptions_in(expected).inspect}"
+ end
+
+ failure_message do |actual|
+ "expected #{@cause} to render raw text variant as expected\n " \
+ "expected: #{surface_descriptions_in(expected).inspect}\n " \
+ "actual: #{actual.inspect}"
+ end
+ end
+
+ shared_examples "XSS-proof rendering of status name" do
+ before do
+ cause["status_name"] = ""
+ end
+
+ it "escapes the status name when rendering HTML" do
+ expect(cause).to render_html_variant(a_string_including("<script>alert('xss')</script>"))
+ end
+
+ it "does not escape the status name when rendering raw text" do
+ expect(cause).to render_raw_variant(a_string_including(""))
+ end
+ end
+
context "when the change was caused by a change to the parent" do
- let(:cause) do
+ subject(:cause) do
{
"type" => "work_package_parent_changed_times",
"work_package_id" => work_package.id
}
end
- context "when rendering HTML variant" do
- let(:html) { true }
-
- context "when the user is able to access the related work package" do
- before do
- allow(WorkPackage).to receive(:visible).with(User.current).and_return(WorkPackage.where(id: work_package.id))
- end
-
- it do
- expect(subject).to eq "#{I18n.t('journals.caused_changes.dates_changed')} " \
- "#{I18n.t('journals.cause_descriptions.work_package_parent_changed_times', link:)}"
- end
+ context "when the user is able to access the related work package" do
+ before do
+ allow(WorkPackage).to receive(:visible).with(User.current).and_return(WorkPackage.where(id: work_package.id))
end
- context "when the user is not able to access the related work package" do
- before do
- allow(WorkPackage).to receive(:visible).with(User.current).and_return(WorkPackage.none)
- end
+ it do
+ link = work_package_html_link
+ expect(cause).to render_html_variant(
+ "#{I18n.t('journals.caused_changes.dates_changed')} " \
+ "#{I18n.t('journals.cause_descriptions.work_package_parent_changed_times', link:)}"
+ )
+ end
- it do
- expect(subject).to eq "#{I18n.t('journals.caused_changes.dates_changed')} " \
- "#{I18n.t('journals.cause_descriptions.unaccessable_work_package_changed')}"
- end
+ it do
+ link = work_package_raw_link
+ expect(cause).to render_raw_variant(
+ "#{I18n.t('journals.caused_changes.dates_changed')} " \
+ "#{I18n.t('journals.cause_descriptions.work_package_parent_changed_times', link:)}"
+ )
end
end
- context "when rendering raw variant" do
- let(:html) { false }
-
- context "when the user is able to access the related work package" do
- before do
- allow(WorkPackage).to receive(:visible).with(User.current).and_return(WorkPackage.where(id: work_package.id))
- end
-
- let(:link) { "##{work_package.id}" }
-
- it do
- expect(subject).to eq "#{I18n.t('journals.caused_changes.dates_changed')} " \
- "#{I18n.t('journals.cause_descriptions.work_package_parent_changed_times', link:)}"
- end
+ context "when the user is not able to access the related work package" do
+ before do
+ allow(WorkPackage).to receive(:visible).with(User.current).and_return(WorkPackage.none)
end
- context "when the user is not able to access the related work package" do
- before do
- allow(WorkPackage).to receive(:visible).with(User.current).and_return(WorkPackage.none)
- end
+ it do
+ expect(cause).to render_html_variant(
+ "#{I18n.t('journals.caused_changes.dates_changed')} " \
+ "#{I18n.t('journals.cause_descriptions.unaccessable_work_package_changed')}"
+ )
+ end
- it do
- expect(subject).to eq "#{I18n.t('journals.caused_changes.dates_changed')} " \
- "#{I18n.t('journals.cause_descriptions.unaccessable_work_package_changed')}"
- end
+ it do
+ expect(cause).to render_raw_variant(
+ "#{I18n.t('journals.caused_changes.dates_changed')} " \
+ "#{I18n.t('journals.cause_descriptions.unaccessable_work_package_changed')}"
+ )
end
end
end
context "when the change was caused by a change to a predecessor" do
- let(:cause) do
+ subject(:cause) do
{
"type" => "work_package_predecessor_changed_times",
"work_package_id" => work_package.id
}
end
- context "when rendering HTML variant" do
- let(:html) { true }
-
- context "when the user is able to access the related work package" do
- before do
- allow(WorkPackage).to receive(:visible).with(User.current).and_return(WorkPackage.where(id: work_package.id))
- end
-
- it do
- expect(subject).to eq "#{I18n.t('journals.caused_changes.dates_changed')} " \
- "#{I18n.t('journals.cause_descriptions.work_package_predecessor_changed_times', link:)}"
- end
+ context "when the user is able to access the related work package" do
+ before do
+ allow(WorkPackage).to receive(:visible).with(User.current).and_return(WorkPackage.where(id: work_package.id))
end
- context "when the user is not able to access the related work package" do
- before do
- allow(WorkPackage).to receive(:visible).with(User.current).and_return(WorkPackage.none)
- end
+ it do
+ link = work_package_html_link
+ expect(cause).to render_html_variant(
+ "#{I18n.t('journals.caused_changes.dates_changed')} " \
+ "#{I18n.t('journals.cause_descriptions.work_package_predecessor_changed_times', link:)}"
+ )
+ end
- it do
- expect(subject).to eq "#{I18n.t('journals.caused_changes.dates_changed')} " \
- "#{I18n.t('journals.cause_descriptions.unaccessable_work_package_changed')}"
- end
+ it do
+ link = work_package_raw_link
+ expect(cause).to render_raw_variant(
+ "#{I18n.t('journals.caused_changes.dates_changed')} " \
+ "#{I18n.t('journals.cause_descriptions.work_package_predecessor_changed_times', link:)}"
+ )
end
end
- context "when rendering raw variant" do
- let(:html) { false }
-
- context "when the user is able to access the related work package" do
- before do
- allow(WorkPackage).to receive(:visible).with(User.current).and_return(WorkPackage.where(id: work_package.id))
- end
-
- let(:link) { "##{work_package.id}" }
-
- it do
- expect(subject).to eq "#{I18n.t('journals.caused_changes.dates_changed')} " \
- "#{I18n.t('journals.cause_descriptions.work_package_predecessor_changed_times', link:)}"
- end
+ context "when the user is not able to access the related work package" do
+ before do
+ allow(WorkPackage).to receive(:visible).with(User.current).and_return(WorkPackage.none)
end
- context "when the user is not able to access the related work package" do
- before do
- allow(WorkPackage).to receive(:visible).with(User.current).and_return(WorkPackage.none)
- end
+ it do
+ expect(cause).to render_html_variant(
+ "#{I18n.t('journals.caused_changes.dates_changed')} " \
+ "#{I18n.t('journals.cause_descriptions.unaccessable_work_package_changed')}"
+ )
+ end
- it do
- expect(subject).to eq "#{I18n.t('journals.caused_changes.dates_changed')} " \
- "#{I18n.t('journals.cause_descriptions.unaccessable_work_package_changed')}"
- end
+ it do
+ expect(cause).to render_raw_variant(
+ "#{I18n.t('journals.caused_changes.dates_changed')} " \
+ "#{I18n.t('journals.cause_descriptions.unaccessable_work_package_changed')}"
+ )
end
end
end
context "when the change was caused by a change to a child" do
- let(:cause) do
+ subject(:cause) do
{
"type" => "work_package_children_changed_times",
"work_package_id" => work_package.id
}
end
- context "when rendering HTML variant" do
- let(:html) { true }
-
- context "when the user is able to access the related work package" do
- before do
- allow(WorkPackage).to receive(:visible).with(User.current).and_return(WorkPackage.where(id: work_package.id))
- end
-
- it do
- expect(subject).to eq "#{I18n.t('journals.caused_changes.dates_changed')} " \
- "#{I18n.t('journals.cause_descriptions.work_package_children_changed_times', link:)}"
- end
+ context "when the user is able to access the related work package" do
+ before do
+ allow(WorkPackage).to receive(:visible).with(User.current).and_return(WorkPackage.where(id: work_package.id))
end
- context "when the user is not able to access the related work package" do
- before do
- allow(WorkPackage).to receive(:visible).with(User.current).and_return(WorkPackage.none)
- end
+ it do
+ link = work_package_html_link
+ expect(cause).to render_html_variant(
+ "#{I18n.t('journals.caused_changes.dates_changed')} " \
+ "#{I18n.t('journals.cause_descriptions.work_package_children_changed_times', link:)}"
+ )
+ end
- it do
- expect(subject).to eq "#{I18n.t('journals.caused_changes.dates_changed')} " \
- "#{I18n.t('journals.cause_descriptions.unaccessable_work_package_changed')}"
- end
+ it do
+ link = work_package_raw_link
+ expect(cause).to render_raw_variant(
+ "#{I18n.t('journals.caused_changes.dates_changed')} " \
+ "#{I18n.t('journals.cause_descriptions.work_package_children_changed_times', link:)}"
+ )
end
end
- context "when rendering raw variant" do
- let(:html) { false }
-
- context "when the user is able to access the related work package" do
- before do
- allow(WorkPackage).to receive(:visible).with(User.current).and_return(WorkPackage.where(id: work_package.id))
- end
-
- let(:link) { "##{work_package.id}" }
-
- it do
- expect(subject).to eq "#{I18n.t('journals.caused_changes.dates_changed')} " \
- "#{I18n.t('journals.cause_descriptions.work_package_children_changed_times', link:)}"
- end
+ context "when the user is not able to access the related work package" do
+ before do
+ allow(WorkPackage).to receive(:visible).with(User.current).and_return(WorkPackage.none)
end
- context "when the user is not able to access the related work package" do
- before do
- allow(WorkPackage).to receive(:visible).with(User.current).and_return(WorkPackage.none)
- end
+ it do
+ expect(cause).to render_html_variant(
+ "#{I18n.t('journals.caused_changes.dates_changed')} " \
+ "#{I18n.t('journals.cause_descriptions.unaccessable_work_package_changed')}"
+ )
+ end
- it do
- expect(subject).to eq "#{I18n.t('journals.caused_changes.dates_changed')} " \
- "#{I18n.t('journals.cause_descriptions.unaccessable_work_package_changed')}"
- end
+ it do
+ expect(cause).to render_raw_variant(
+ "#{I18n.t('journals.caused_changes.dates_changed')} " \
+ "#{I18n.t('journals.cause_descriptions.unaccessable_work_package_changed')}"
+ )
end
end
end
context "when the change was caused by working day changes" do
- let(:cause) do
+ subject(:cause) do
{
"type" => "working_days_changed",
"changed_days" => {
@@ -259,233 +274,261 @@
}
end
- context "when rendering HTML variant" do
- let(:html) { true }
+ it do
+ changes = [
+ I18n.t("journals.cause_descriptions.working_days_changed.days.non_working", day: WeekDay.find_by!(day: 2).name),
+ I18n.t("journals.cause_descriptions.working_days_changed.days.working", day: WeekDay.find_by!(day: 6).name),
+ I18n.t("journals.cause_descriptions.working_days_changed.dates.working", date: I18n.l(Date.new(2023, 1, 1))),
+ I18n.t("journals.cause_descriptions.working_days_changed.dates.non_working", date: I18n.l(Date.new(2023, 12, 24)))
+ ].join(", ")
+ expect(cause).to render_html_variant(
+ "#{I18n.t('journals.caused_changes.dates_changed')} " \
+ "#{I18n.t('journals.cause_descriptions.working_days_changed.changed', changes:)}"
+ )
+ end
+
+ it do
+ changes = [
+ I18n.t("journals.cause_descriptions.working_days_changed.days.non_working", day: WeekDay.find_by!(day: 2).name),
+ I18n.t("journals.cause_descriptions.working_days_changed.days.working", day: WeekDay.find_by!(day: 6).name),
+ I18n.t("journals.cause_descriptions.working_days_changed.dates.working", date: I18n.l(Date.new(2023, 1, 1))),
+ I18n.t("journals.cause_descriptions.working_days_changed.dates.non_working", date: I18n.l(Date.new(2023, 12, 24)))
+ ].join(", ")
+ expect(cause).to render_raw_variant(
+ "#{I18n.t('journals.caused_changes.dates_changed')} " \
+ "#{I18n.t('journals.cause_descriptions.working_days_changed.changed', changes:)}"
+ )
+ end
+ end
- it do
- changes = [
- I18n.t("journals.cause_descriptions.working_days_changed.days.non_working", day: WeekDay.find_by!(day: 2).name),
- I18n.t("journals.cause_descriptions.working_days_changed.days.working", day: WeekDay.find_by!(day: 6).name),
- I18n.t("journals.cause_descriptions.working_days_changed.dates.working", date: I18n.l(Date.new(2023, 1, 1))),
- I18n.t("journals.cause_descriptions.working_days_changed.dates.non_working", date: I18n.l(Date.new(2023, 12, 24)))
- ].join(", ")
- expect(subject).to eq "#{I18n.t('journals.caused_changes.dates_changed')} " \
- "#{I18n.t('journals.cause_descriptions.working_days_changed.changed', changes:)}"
- end
+ context "when a change of status % complete is the cause" do
+ shared_let(:status) { create(:status, name: "In progress", default_done_ratio: 40) }
+ subject(:cause) do
+ {
+ "type" => "status_changed",
+ "status_name" => status.name,
+ "status_id" => status.id,
+ "status_changes" => { "default_done_ratio" => [20, 40] }
+ }
end
- context "when rendering raw variant" do
- let(:html) { false }
+ it do
+ expect(cause).to render_html_variant("Status 'In progress' " \
+ "% complete changed from 20% to 40%")
+ end
- it do
- changes = [
- I18n.t("journals.cause_descriptions.working_days_changed.days.non_working", day: WeekDay.find_by!(day: 2).name),
- I18n.t("journals.cause_descriptions.working_days_changed.days.working", day: WeekDay.find_by!(day: 6).name),
- I18n.t("journals.cause_descriptions.working_days_changed.dates.working", date: I18n.l(Date.new(2023, 1, 1))),
- I18n.t("journals.cause_descriptions.working_days_changed.dates.non_working", date: I18n.l(Date.new(2023, 12, 24)))
- ].join(", ")
- expect(subject).to eq "#{I18n.t('journals.caused_changes.dates_changed')} " \
- "#{I18n.t('journals.cause_descriptions.working_days_changed.changed', changes:)}"
- end
+ it do
+ expect(cause).to render_raw_variant("Status 'In progress' % complete changed from 20% to 40%")
end
+
+ it_behaves_like "XSS-proof rendering of status name"
end
- context "when a change of status % complete is the cause" do
- shared_let(:status) { create(:status, name: "In progress", default_done_ratio: 40) }
- let(:cause) do
+ context "when a status being excluded from totals is the cause" do
+ shared_let(:status) { create(:status, name: "Rejected") }
+ subject(:cause) do
{
- "type" => "status_p_complete_changed",
+ "type" => "status_changed",
"status_name" => status.name,
"status_id" => status.id,
- "status_p_complete_change" => [20, 40]
+ "status_changes" => { "excluded_from_totals" => [false, true] }
}
end
- context "when rendering HTML variant" do
- let(:html) { true }
-
- it do
- expect(subject).to eq "#{I18n.t('journals.caused_changes.status_p_complete_changed')} " \
- "% complete value for status 'In progress' changed from 20% to 40%"
- end
+ it do
+ expect(cause).to render_html_variant(
+ "Status 'Rejected' now excluded from hierarchy totals"
+ )
+ end
- it "escapes the status name" do
- cause["status_name"] = ""
- expect(subject).to eq "#{I18n.t('journals.caused_changes.status_p_complete_changed')} " \
- "% complete value for status '<script>alert('xss')</script>' " \
- "changed from 20% to 40%"
- end
+ it do
+ expect(cause).to render_raw_variant(
+ "Status 'Rejected' now excluded from hierarchy totals"
+ )
end
- context "when rendering raw variant" do
- let(:html) { false }
+ it_behaves_like "XSS-proof rendering of status name"
+ end
- it do
- expect(subject).to eq "#{I18n.t('journals.caused_changes.status_p_complete_changed')} " \
- "% complete value for status 'In progress' changed from 20% to 40%"
- end
+ context "when a status being no longer excluded from totals is the cause" do
+ shared_let(:status) { create(:status, name: "Rejected") }
+ subject(:cause) do
+ {
+ "type" => "status_changed",
+ "status_name" => status.name,
+ "status_id" => status.id,
+ "status_changes" => { "excluded_from_totals" => [true, false] }
+ }
+ end
- it "does not escape the status name" do
- cause["status_name"] = ""
- expect(subject).to eq "#{I18n.t('journals.caused_changes.status_p_complete_changed')} " \
- "% complete value for status '' changed from 20% to 40%"
- end
+ it do
+ expect(cause).to render_html_variant(
+ "Status 'Rejected' now included in hierarchy totals"
+ )
end
+
+ it do
+ expect(cause).to render_raw_variant(
+ "Status 'Rejected' now included in hierarchy totals"
+ )
+ end
+
+ it_behaves_like "XSS-proof rendering of status name"
end
context "when a change of progress calculation mode to status-based is the cause" do
- let(:cause) do
+ subject(:cause) do
{
"type" => "progress_mode_changed_to_status_based"
}
end
- context "when rendering HTML variant" do
- let(:html) { true }
+ it do
+ expect(cause).to render_html_variant(
+ "Progress calculation updated " \
+ "Progress calculation mode set to status-based"
+ )
+ end
- it do
- expect(subject).to eq "#{I18n.t('journals.caused_changes.progress_mode_changed_to_status_based')} " \
- "Progress calculation mode set to status-based"
- end
+ it do
+ expect(cause).to render_raw_variant(
+ "Progress calculation updated " \
+ "Progress calculation mode set to status-based"
+ )
end
+ end
- context "when rendering raw variant" do
- let(:html) { false }
+ context "when both a change of status % complete and excluded from totals is the cause" do
+ shared_let(:status) { create(:status, name: "In progress", default_done_ratio: 40) }
+ subject(:cause) do
+ {
+ "type" => "status_changed",
+ "status_name" => status.name,
+ "status_id" => status.id,
+ "status_changes" => { "default_done_ratio" => [20, 40],
+ "excluded_from_totals" => [false, true] }
+ }
+ end
- it do
- expect(subject).to eq "#{I18n.t('journals.caused_changes.progress_mode_changed_to_status_based')} " \
- "Progress calculation mode set to status-based"
- end
+ it do
+ expect(cause).to render_html_variant("Status 'In progress' " \
+ "% complete changed from 20% to 40% and now excluded from hierarchy totals")
+ end
+
+ it do
+ expect(cause).to render_raw_variant("Status 'In progress' " \
+ "% complete changed from 20% to 40% and now excluded from hierarchy totals")
end
+
+ it_behaves_like "XSS-proof rendering of status name"
end
context "when cause is a system update: change of progress calculation mode from disabled to work-based" do
- let(:cause) do
+ subject(:cause) do
{
"type" => "system_update",
"feature" => "progress_calculation_adjusted_from_disabled_mode"
}
end
- context "when rendering HTML variant" do
- let(:html) { true }
-
- it do
- href = OpenProject::Static::Links.links[:blog_article_progress_changes][:href]
- expect(subject).to eq "OpenProject system update: Progress calculation automatically " \
- "set to work-based mode and adjusted with version update."
- end
+ it do
+ href = OpenProject::Static::Links.links[:blog_article_progress_changes][:href]
+ expect(cause).to render_html_variant(
+ "OpenProject system update: Progress calculation automatically " \
+ "set to work-based mode and adjusted with version update."
+ )
end
- context "when rendering raw variant" do
- let(:html) { false }
-
- it do
- expect(subject).to eq "OpenProject system update: Progress calculation automatically " \
- "set to work-based mode and adjusted with version update."
- end
+ it do
+ expect(cause).to render_raw_variant(
+ "OpenProject system update: Progress calculation automatically " \
+ "set to work-based mode and adjusted with version update."
+ )
end
end
context "when cause is a system update: progress calculation adjusted" do
- let(:cause) do
+ subject(:cause) do
{
"type" => "system_update",
"feature" => "progress_calculation_adjusted"
}
end
- context "when rendering HTML variant" do
- let(:html) { true }
-
- it do
- href = OpenProject::Static::Links.links[:blog_article_progress_changes][:href]
- expect(subject).to eq "OpenProject system update: Progress calculation automatically " \
- "adjusted with version update."
- end
+ it do
+ href = OpenProject::Static::Links.links[:blog_article_progress_changes][:href]
+ expect(cause).to render_html_variant(
+ "OpenProject system update: Progress calculation automatically " \
+ "adjusted with version update."
+ )
end
- context "when rendering raw variant" do
- let(:html) { false }
-
- it do
- expect(subject).to eq "OpenProject system update: Progress calculation automatically " \
- "adjusted with version update."
- end
+ it do
+ expect(cause).to render_raw_variant(
+ "OpenProject system update: Progress calculation automatically adjusted with version update."
+ )
end
context "with previous feature key 'progress_calculation_changed'" do
- let(:cause) do
- {
- "type" => "system_update",
- "feature" => "progress_calculation_changed"
- }
+ before do
+ cause["feature"] = "progress_calculation_changed"
end
- let(:html) { false }
it "is rendered like 'progress_calculation_adjusted'" do
- expect(subject).to eq "OpenProject system update: Progress calculation automatically " \
- "adjusted with version update."
+ expect(cause).to render_raw_variant(
+ "OpenProject system update: Progress calculation automatically adjusted with version update."
+ )
end
end
end
context "when cause is a system update: totals removed from childless work packages" do
- let(:cause) do
+ subject(:cause) do
{
"type" => "system_update",
"feature" => "totals_removed_from_childless_work_packages"
}
end
- context "when rendering HTML variant" do
- let(:html) { true }
-
- it do
- href = OpenProject::Static::Links.links[:release_notes_14_0_1][:href]
- expect(subject).to eq "OpenProject system update: Work and progress totals " \
- "automatically removed for non-parent work packages with " \
- "version update. " \
- "This is a maintenance task and can be safely ignored."
- end
+ it do
+ href = OpenProject::Static::Links.links[:release_notes_14_0_1][:href]
+ expect(cause).to render_html_variant(
+ "OpenProject system update: Work and progress totals " \
+ "automatically removed for non-parent work packages with " \
+ "version update. " \
+ "This is a maintenance task and can be safely ignored."
+ )
end
- context "when rendering raw variant" do
- let(:html) { false }
-
- it do
- expect(subject).to eq "OpenProject system update: Work and progress totals " \
- "automatically removed for non-parent work packages with " \
- "version update. " \
- "This is a maintenance task and can be safely ignored."
- end
+ it do
+ expect(cause).to render_raw_variant(
+ "OpenProject system update: Work and progress totals " \
+ "automatically removed for non-parent work packages with version update. " \
+ "This is a maintenance task and can be safely ignored."
+ )
end
end
context "when the change was caused by a system update" do
- let(:cause) do
+ subject(:cause) do
{
"type" => "system_update",
"feature" => "file_links_journal"
}
end
- context "when rendering HTML variant" do
- let(:html) { true }
-
- it do
- expect(subject).to eq "#{I18n.t('journals.caused_changes.system_update')} " \
- "#{I18n.t('journals.cause_descriptions.system_update.file_links_journal')}"
- end
+ it do
+ expect(cause).to render_html_variant(
+ "#{I18n.t('journals.caused_changes.system_update')} " \
+ "#{I18n.t('journals.cause_descriptions.system_update.file_links_journal')}"
+ )
end
- context "when rendering raw variant" do
- let(:html) { false }
-
- it do
- expect(subject).to eq "#{I18n.t('journals.caused_changes.system_update')} " \
- "#{I18n.t('journals.cause_descriptions.system_update.file_links_journal')}"
- end
+ it do
+ expect(cause).to render_raw_variant(
+ "#{I18n.t('journals.caused_changes.system_update')} " \
+ "#{I18n.t('journals.cause_descriptions.system_update.file_links_journal')}"
+ )
end
end
end
diff --git a/spec/models/notifications/scopes/unsent_reminders_before_spec.rb b/spec/models/notifications/scopes/unsent_reminders_before_spec.rb
index c739b814ec49..9d84b3ab0175 100644
--- a/spec/models/notifications/scopes/unsent_reminders_before_spec.rb
+++ b/spec/models/notifications/scopes/unsent_reminders_before_spec.rb
@@ -39,62 +39,76 @@
Time.current
end
- let(:notification) do
+ let!(:notification) do
create(:notification,
recipient: notification_recipient,
read_ian: notification_read_ian,
mail_reminder_sent: notification_mail_reminder_sent,
+ mail_alert_sent: notification_mail_alert_sent,
created_at: notification_created_at)
end
let(:notification_mail_reminder_sent) { false }
+ let(:notification_mail_alert_sent) { false }
let(:notification_read_ian) { false }
let(:notification_created_at) { 10.minutes.ago }
let(:notification_recipient) { recipient }
- let!(:notifications) { notification }
-
- shared_examples_for "is empty" do
- it "is empty" do
- expect(scope)
- .to be_empty
- end
- end
-
- context "with a unread and not reminded notification that was created before the time and for the user" do
+ context "with an unread, not alerted about and not reminded notification that was created before the time and for the user" do
it "returns the notification" do
- expect(scope)
- .to contain_exactly(notification)
+ expect(scope).to contain_exactly(notification)
end
end
- context "with a unread and not reminded notification that was created after the time and for the user" do
+ context "with a notification that was created after the time" do
let(:notification_created_at) { 10.minutes.from_now }
- it_behaves_like "is empty"
+ it { is_expected.to be_empty }
end
- context "with a unread and not reminded notification that was created before the time and for different user" do
+ context "with a notification that was created for different user" do
let(:notification_recipient) { create(:user) }
- it_behaves_like "is empty"
+ it { is_expected.to be_empty }
end
- context "with a unread and not reminded notification created before the time and for the user" do
+ context "with a notification reminded mark set to nil" do
let(:notification_mail_reminder_sent) { nil }
- it_behaves_like "is empty"
+ it { is_expected.to be_empty }
end
- context "with a unread but reminded notification created before the time and for the user" do
+ context "with a reminded notification" do
let(:notification_mail_reminder_sent) { true }
- it_behaves_like "is empty"
+ it { is_expected.to be_empty }
+ end
+
+ context "with a notification read mark set to nil" do
+ let(:notification_read_ian) { nil }
+
+ it "returns the notification" do
+ expect(scope).to contain_exactly(notification)
+ end
end
- context "with a read notification that was created before the time" do
+ context "with a read notification" do
let(:notification_read_ian) { true }
- it_behaves_like "is empty"
+ it { is_expected.to be_empty }
+ end
+
+ context "with a notification alert mark set to nil" do
+ let(:notification_mail_alert_sent) { nil }
+
+ it "returns the notification" do
+ expect(scope).to contain_exactly(notification)
+ end
+ end
+
+ context "with a notification about which user was already alerted" do
+ let(:notification_mail_alert_sent) { true }
+
+ it { is_expected.to be_empty }
end
end
end
diff --git a/spec/models/work_packages/pdf_export/work_package_to_pdf_spec.rb b/spec/models/work_packages/pdf_export/work_package_to_pdf_spec.rb
index f6fd8f60c8db..6078c2c63782 100644
--- a/spec/models/work_packages/pdf_export/work_package_to_pdf_spec.rb
+++ b/spec/models/work_packages/pdf_export/work_package_to_pdf_spec.rb
@@ -36,10 +36,47 @@
t.attribute_groups.first.attributes.push(cf_disabled_in_project.attribute_name, cf_long_text.attribute_name)
end
end
+ let(:parent_project) do
+ create(:project, name: "Parent project")
+ end
+ let(:project_custom_field_bool) { create(:project_custom_field, :boolean,
+ name: "Boolean project custom field") }
+ let(:project_custom_field_string) {
+ create(:project_custom_field, :string,
+ name: "Secret string", default_value: "admin eyes only",
+ visible: false)
+ }
+ let(:project_custom_field_long_text) {
+ create(:project_custom_field, :text,
+ name: "Rich text project custom field",
+ default_value: "rich text field value"
+ )
+ }
let(:project) do
create(:project,
name: "Foo Bla. Report No. 4/2021 with/for Case 42",
types: [type],
+ public: true,
+ status_code: "on_track",
+ active: true,
+ parent: parent_project,
+ custom_field_values: {
+ project_custom_field_bool.id => true,
+ project_custom_field_long_text.id => "foo",
+ },
+ work_package_custom_fields: [cf_long_text, cf_disabled_in_project, cf_global_bool],
+ work_package_custom_field_ids: [cf_long_text.id, cf_global_bool.id]) # cf_disabled_in_project.id is disabled
+ end
+ let(:forbidden_project) do
+ create(:project,
+ name: "Forbidden project",
+ types: [type],
+ id: 666,
+ identifier: "forbidden-project",
+ public: false,
+ status_code: "on_track",
+ active: true,
+ parent: parent_project,
work_package_custom_fields: [cf_long_text, cf_disabled_in_project, cf_global_bool],
work_package_custom_field_ids: [cf_long_text.id, cf_global_bool.id]) # cf_disabled_in_project.id is disabled
end
@@ -47,12 +84,20 @@
create(:user,
member_with_permissions: { project => %w[view_work_packages export_work_packages] })
end
+ let(:another_user) do
+ create(:user, firstname: "Secret User")
+ end
+ let(:category) { create(:category, project:, name: "Demo") }
+ let(:version) { create(:version, project:) }
let(:export_time) { DateTime.new(2023, 6, 30, 23, 59) }
let(:export_time_formatted) { format_time(export_time, true) }
let(:image_path) { Rails.root.join("spec/fixtures/files/image.png") }
+ let(:priority) { create(:priority_normal) }
let(:image_attachment) { Attachment.new author: user, file: File.open(image_path) }
let(:attachments) { [image_attachment] }
- let(:cf_long_text) { create(:issue_custom_field, :text, name: "LongText") }
+ let(:cf_long_text_description) { "" }
+ let(:cf_long_text) { create(:issue_custom_field, :text,
+ name: "Work Package Custom Field Long Text") }
let!(:cf_disabled_in_project) do
# NOT enabled by project.work_package_custom_field_ids => NOT in PDF
create(:float_wp_custom_field, name: "DisabledCustomField")
@@ -60,13 +105,16 @@
let(:cf_global_bool) do
create(
:work_package_custom_field,
+ name: "Work Package Custom Field Boolean",
field_format: "bool",
is_for_all: true,
default_value: true
)
end
- let(:work_package) do
- description = <<~DESCRIPTION
+ let(:status) { create(:status, name: "random", is_default: true) }
+ let!(:parent_work_package) { create(:work_package, type:, subject: "Parent wp") }
+ let(:description) do
+ <<~DESCRIPTION
**Lorem** _ipsum_ ~~dolor~~ `sit` [amet](https://example.com/), consetetur sadipscing elitr.
@OpenProject Admin

@@ -80,14 +128,32 @@
Foo
DESCRIPTION
+ end
+ let(:work_package) do
create(:work_package,
+ id: 1,
project:,
type:,
subject: "Work package 1",
+ start_date: "2024-05-30",
+ due_date: "2024-05-30",
+ created_at: export_time,
+ updated_at: export_time,
+ author: user,
+ assigned_to: user,
+ responsible: user,
story_points: 1,
+ estimated_hours: 10,
+ done_ratio: 25,
+ remaining_hours: 9,
+ parent: parent_work_package,
+ priority:,
+ version:,
+ status:,
+ category:,
description:,
custom_values: {
- cf_long_text.id => "foo",
+ cf_long_text.id => cf_long_text_description,
cf_disabled_in_project.id => "6.25",
cf_global_bool.id => true
}).tap do |wp|
@@ -96,6 +162,24 @@
.and_return attachments
end
end
+ let(:forbidden_work_package) do
+ create(:work_package,
+ id: 10,
+ project: forbidden_project,
+ type:,
+ subject: "forbidden Work package",
+ start_date: "2024-05-30",
+ due_date: "2024-05-30",
+ created_at: export_time,
+ updated_at: export_time,
+ author: another_user,
+ assigned_to: another_user
+ ).tap do |wp|
+ allow(wp)
+ .to receive(:attachments)
+ .and_return attachments
+ end
+ end
let(:options) { {} }
let(:exporter) do
described_class.new(work_package, options)
@@ -109,6 +193,16 @@
export.export!
end
end
+ let(:expected_details) do
+ ["#{type.name} ##{work_package.id} - #{work_package.subject}"] +
+ exporter.send(:attributes_data_by_wp, work_package)
+ .flat_map do |item|
+ value = get_column_value(item[:name])
+ result = [item[:label].upcase]
+ result << value if value.present?
+ result
+ end
+ end
def get_column_value(column_name)
formatter = Exports::Register.formatter_for(WorkPackage, column_name, :pdf)
@@ -125,30 +219,203 @@ def get_column_value(column_name)
end
describe "with a request for a PDF" do
- it "contains correct data" do
- details = exporter.send(:attributes_data_by_wp, work_package)
- .flat_map do |item|
- value = get_column_value(item[:name])
- result = [item[:label].upcase]
- result << value if value.present?
- result
+ describe "with rich text and images" do
+ let(:cf_long_text_description) { "foo" }
+ it "contains correct data" do
+ result = pdf[:strings]
+ expected_result = [
+ *expected_details,
+ label_title(:description),
+ "Lorem", " ", "ipsum", " ", "dolor", " ", "sit", " ",
+ "amet", ", consetetur sadipscing elitr.", " ", "@OpenProject Admin",
+ "Image Caption",
+ "Foo",
+ cf_long_text.name, "foo",
+ "1", export_time_formatted, project.name
+ ].flatten
+ # Joining the results for comparison since word wrapping leads to a different array for the same content
+ expect(result.join(" ")).to eq(expected_result.join(" "))
+ expect(result.join(" ")).not_to include("DisabledCustomField")
+ expect(pdf[:images].length).to eq(2)
+ end
+ end
+
+ describe "with embedded work package attributes" do
+ let(:supported_work_package_embeds) do
+ [
+ ["assignee", user.name],
+ ["author", user.name],
+ ["category", category.name],
+ ["createdAt", export_time_formatted],
+ ["updatedAt", export_time_formatted],
+ ["estimatedTime", "10.0 h"],
+ ["remainingTime", "9.0 h"],
+ ["version", version.name],
+ ["responsible", user.name],
+ ["dueDate", "05/30/2024"],
+ ["spentTime", "0.0 h"],
+ ["startDate", "05/30/2024"],
+ ["parent", "#{type.name} ##{parent_work_package.id}: #{parent_work_package.name}"],
+ ["priority", priority.name],
+ ["project", project.name],
+ ["status", status.name],
+ ["subject", "Work package 1"],
+ ["type", type.name],
+ ["description", "[#{I18n.t('export.macro.rich_text_unsupported')}]"]
+ ]
+ end
+ let(:supported_work_package_embeds_table) do
+ supported_work_package_embeds.map do |embed|
+ "
workPackageLabel:#{embed[0]}
workPackageValue:#{embed[0]}
"
+ end
+ end
+ let(:description) do
+ <<~DESCRIPTION
+ ## Work package attributes and labels
+
+
+ `projectValue:2:status projectLabel:status`
+
+ ```
+ projectValue:3:status
+ projectLabel:status
+ ```
+
+ Project by identifier:
+ projectValue:"#{project.identifier}":active
+
+ Project not found:
+ projectValue:1234567890:active
+ Access denied:
+ projectValue:#{forbidden_project.id}:active
+ Access denied by identifier:
+ projectValue:"#{forbidden_project.identifier}":active
+ DESCRIPTION
+ end
+ it "contains resolved attributes and labels" do
+ result = pdf[:strings]
+ expected_result = [
+ *expected_details,
+ label_title(:description),
+ "Project attributes and labels",
+ supported_project_embeds.map do |embed|
+ [Project.human_attribute_name(
+ API::Utilities::PropertyNameConverter.to_ar_name(embed[0].to_sym, context: project)
+ ), embed[1]]
+ end,
+ "Custom field boolean", I18n.t(:general_text_Yes),
+ "Custom field rich text", "[#{I18n.t('export.macro.rich_text_unsupported')}]",
+ "Custom field hidden",
+
+ "No replacement of:", "projectValue:1:status", "projectLabel:status",
+ "projectValue:2:status projectLabel:status",
+ "projectValue:3:status", "projectLabel:status",
+
+ "1", export_time_formatted, project.name,
+
+ "Project by identifier:", " ", I18n.t(:general_text_Yes),
+ "Project not found: ",
+ "[#{I18n.t('export.macro.error', message:
+ I18n.t('export.macro.resource_not_found', resource: "Project 1234567890"))}] ",
+ "Access denied: ",
+ "[#{I18n.t('export.macro.error', message:
+ I18n.t('export.macro.resource_not_found', resource: "Project #{forbidden_project.id}"))}] ",
+ "Access denied by identifier:", " ", "[Macro error, resource not found: Project", "forbidden-project]",
+
+ "2", export_time_formatted, project.name,
+ ].flatten
+ expect(result.join(" ")).to eq(expected_result.join(" "))
end
- # Joining the results for comparison since word wrapping leads to a different array for the same content
- result = pdf[:strings].join(" ")
- expected_result = [
- "#{type.name} ##{work_package.id} - #{work_package.subject}",
- *details,
- label_title(:description),
- "Lorem", " ", "ipsum", " ", "dolor", " ", "sit", " ",
- "amet", ", consetetur sadipscing elitr.", " ", "@OpenProject Admin",
- "Image Caption",
- "Foo",
- "LongText", "foo",
- "1", export_time_formatted, project.name
- ].join(" ")
- expect(result).to eq(expected_result)
- expect(result).not_to include("DisabledCustomField")
- expect(pdf[:images].length).to eq(2)
end
end
end
diff --git a/spec/services/duration_converter_spec.rb b/spec/services/duration_converter_spec.rb
new file mode 100644
index 000000000000..ae41cc833a2f
--- /dev/null
+++ b/spec/services/duration_converter_spec.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+# -- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2024 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+# ++
+
+require "spec_helper"
+
+RSpec.describe DurationConverter do
+ describe ".parse" do
+ it "returns 0 when given 0 duration" do
+ expect(described_class.parse("0 hrs")).to eq(0)
+ end
+
+ it "works with ChronicDuration defaults otherwise" do
+ expect(described_class.parse("5 hrs 30 mins")).to eq(5.5)
+ end
+
+ it "assumes hours as the default unit for input if no other units given" do
+ expect(described_class.parse("5.75")).to eq(5.75)
+ end
+
+ it "assumes the next logical unit if at least one unit is given" do
+ expect(described_class.parse("2h 15")).to eq(2.25)
+ expect(described_class.parse("1d 24")).to eq(32)
+ expect(described_class.parse("1w 1")).to eq(48)
+ expect(described_class.parse("1mo 1")).to eq(200)
+ expect(described_class.parse("1mo 1w 1d 1h 30")).to eq(209.5)
+ end
+ end
+
+ describe ".output" do
+ it "returns nil when given nil" do
+ expect(described_class.output(nil)).to be_nil
+ end
+
+ it "returns 0 h when given 0" do
+ expect(described_class.output(0)).to eq("0h")
+ end
+
+ it "works with ChronicDuration defaults otherwise in :short format" do
+ expect(described_class.output(5.75))
+ .to eq("5h 45m")
+ end
+
+ it "ignores seconds and keep the nearest minute" do
+ expect(described_class.output(0.28))
+ .to eq("17m")
+ expect(described_class.output(2.23))
+ .to eq("2h 14m")
+ end
+ end
+end
diff --git a/spec/services/notifications/create_from_model_service_work_package_spec.rb b/spec/services/notifications/create_from_model_service_work_package_spec.rb
index 6c28374eb004..c582162b355e 100644
--- a/spec/services/notifications/create_from_model_service_work_package_spec.rb
+++ b/spec/services/notifications/create_from_model_service_work_package_spec.rb
@@ -121,7 +121,7 @@
{
read_ian: false,
reason: :assigned,
- mail_alert_sent: false,
+ mail_alert_sent: nil,
mail_reminder_sent: false
}
end
@@ -139,7 +139,7 @@
{
read_ian: false,
reason: :assigned,
- mail_alert_sent: false,
+ mail_alert_sent: nil,
mail_reminder_sent: false
}
end
@@ -168,7 +168,7 @@
{
read_ian: false,
reason: :assigned,
- mail_alert_sent: false,
+ mail_alert_sent: nil,
mail_reminder_sent: false
}
end
@@ -212,7 +212,7 @@
{
read_ian: false,
reason: :responsible,
- mail_alert_sent: false,
+ mail_alert_sent: nil,
mail_reminder_sent: false
}
end
@@ -265,7 +265,7 @@
{
read_ian: false,
reason: :watched,
- mail_alert_sent: false,
+ mail_alert_sent: nil,
mail_reminder_sent: false
}
end
@@ -283,7 +283,7 @@
{
read_ian: false,
reason: :watched,
- mail_alert_sent: false,
+ mail_alert_sent: nil,
mail_reminder_sent: false
}
end
@@ -332,7 +332,7 @@
{
read_ian: false,
reason: :created,
- mail_alert_sent: false,
+ mail_alert_sent: nil,
mail_reminder_sent: false
}
end
@@ -350,7 +350,7 @@
{
read_ian: false,
reason: :created,
- mail_alert_sent: false,
+ mail_alert_sent: nil,
mail_reminder_sent: false
}
end
@@ -380,7 +380,7 @@
{
read_ian: false,
reason: :created,
- mail_alert_sent: false,
+ mail_alert_sent: nil,
mail_reminder_sent: false
}
end
@@ -429,7 +429,7 @@
{
read_ian: false,
reason: :shared,
- mail_alert_sent: false,
+ mail_alert_sent: nil,
mail_reminder_sent: false
}
end
@@ -477,7 +477,7 @@
{
read_ian: false,
reason: :created,
- mail_alert_sent: false,
+ mail_alert_sent: nil,
mail_reminder_sent: false
}
end
@@ -533,7 +533,7 @@
{
read_ian: false,
reason: :commented,
- mail_alert_sent: false,
+ mail_alert_sent: nil,
mail_reminder_sent: false
}
end
@@ -582,7 +582,7 @@
{
read_ian: false,
reason: :processed,
- mail_alert_sent: false,
+ mail_alert_sent: nil,
mail_reminder_sent: false
}
end
@@ -631,7 +631,7 @@
{
read_ian: false,
reason: :prioritized,
- mail_alert_sent: false,
+ mail_alert_sent: nil,
mail_reminder_sent: false
}
end
@@ -680,7 +680,7 @@
{
read_ian: false,
reason: :scheduled,
- mail_alert_sent: false,
+ mail_alert_sent: nil,
mail_reminder_sent: false
}
end
@@ -729,7 +729,7 @@
{
read_ian: false,
reason: :scheduled,
- mail_alert_sent: false,
+ mail_alert_sent: nil,
mail_reminder_sent: false
}
end
@@ -762,7 +762,7 @@
{
read_ian: false,
reason: :assigned,
- mail_alert_sent: false,
+ mail_alert_sent: nil,
mail_reminder_sent: false
}
end
@@ -991,16 +991,7 @@
end
let(:author) { recipient }
- it_behaves_like "creates notification" do
- let(:notification_channel_reasons) do
- {
- read_ian: false,
- reason: :mentioned,
- mail_alert_sent: false,
- mail_reminder_sent: false
- }
- end
- end
+ it_behaves_like "creates no notification"
end
context "when there is already a notification for the journal (because it was aggregated)" do
@@ -1082,16 +1073,7 @@
end
let(:author) { recipient }
- it_behaves_like "creates notification" do
- let(:notification_channel_reasons) do
- {
- read_ian: false,
- reason: :mentioned,
- mail_alert_sent: false,
- mail_reminder_sent: false
- }
- end
- end
+ it_behaves_like "creates no notification"
end
end
diff --git a/spec/services/notifications/mail_service_mentioned_integration_spec.rb b/spec/services/notifications/mail_service_mentioned_integration_spec.rb
index 22bb27e282ef..392b5b433390 100644
--- a/spec/services/notifications/mail_service_mentioned_integration_spec.rb
+++ b/spec/services/notifications/mail_service_mentioned_integration_spec.rb
@@ -75,7 +75,7 @@ def expect_assigned_notification
expect(assigned_notification).to be_present
expect(assigned_notification.recipient).to eq assignee
expect(assigned_notification.read_ian).to be false
- expect(assigned_notification.mail_alert_sent).to be false
+ expect(assigned_notification.mail_alert_sent).to be_nil
end
it "triggers only one mention notification mail when editing attributes afterwards" do
diff --git a/spec/services/project_custom_field_project_mappings/bulk_create_service_spec.rb b/spec/services/project_custom_field_project_mappings/bulk_create_service_spec.rb
new file mode 100644
index 000000000000..464f6c3663ba
--- /dev/null
+++ b/spec/services/project_custom_field_project_mappings/bulk_create_service_spec.rb
@@ -0,0 +1,113 @@
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2012-2024 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+require "spec_helper"
+
+RSpec.describe ProjectCustomFieldProjectMappings::BulkCreateService do
+ shared_let(:project_custom_field) { create(:project_custom_field) }
+
+ context "with admin permissions" do
+ let(:user) { create(:admin) }
+
+ context "with a single project" do
+ let(:project) { create(:project) }
+ let(:instance) { described_class.new(user:, project:, project_custom_field:) }
+
+ it "creates the mappings" do
+ expect { instance.call }.to change(ProjectCustomFieldProjectMapping, :count).by(1)
+
+ aggregate_failures "creates the mapping for the correct project and custom field" do
+ expect(ProjectCustomFieldProjectMapping.last.project).to eq(project)
+ expect(ProjectCustomFieldProjectMapping.last.project_custom_field).to eq(project_custom_field)
+ end
+ end
+ end
+
+ context "with subprojects" do
+ let(:project) { create(:project) }
+ let!(:subproject) { create(:project, parent: project) }
+ let!(:subproject2) { create(:project, parent: subproject) }
+
+ it "creates the mappings for the project and sub-projects" do
+ create_service = described_class.new(user:, project: project.reload, project_custom_field:,
+ include_sub_projects: true)
+
+ expect { create_service.call }.to change(ProjectCustomFieldProjectMapping, :count).by(3)
+
+ aggregate_failures "creates the mapping for the correct project and custom field" do
+ expect(ProjectCustomFieldProjectMapping.where(project_custom_field:).pluck(:project_id))
+ .to contain_exactly(project.id, subproject.id, subproject2.id)
+ end
+ end
+ end
+ end
+
+ context "with non-admin but sufficient permissions" do
+ let(:user) do
+ create(:user,
+ member_with_permissions: {
+ project => %w[
+ view_work_packages
+ edit_project
+ select_project_custom_fields
+ ]
+ })
+ end
+
+ let(:project) { create(:project) }
+ let(:instance) { described_class.new(user:, project:, project_custom_field:) }
+
+ it "creates the mappings" do
+ expect { instance.call }.to change(ProjectCustomFieldProjectMapping, :count).by(1)
+
+ aggregate_failures "creates the mapping for the correct project and custom field" do
+ expect(ProjectCustomFieldProjectMapping.last.project).to eq(project)
+ expect(ProjectCustomFieldProjectMapping.last.project_custom_field).to eq(project_custom_field)
+ end
+ end
+ end
+
+ context "without sufficient permissions" do
+ let(:user) do
+ create(:user,
+ member_with_permissions: {
+ project => %w[
+ view_work_packages
+ edit_project
+ ]
+ })
+ end
+ let(:project) { create(:project) }
+ let(:instance) { described_class.new(user:, project:, project_custom_field:) }
+
+ it "does not create the mappings" do
+ expect { instance.call }.not_to change(ProjectCustomFieldProjectMapping, :count)
+ expect(instance.call).to be_failure
+ end
+ end
+end
diff --git a/spec/services/settings/working_days_update_service_spec.rb b/spec/services/settings/working_days_and_hours_update_service_spec.rb
similarity index 94%
rename from spec/services/settings/working_days_update_service_spec.rb
rename to spec/services/settings/working_days_and_hours_update_service_spec.rb
index 597466215d65..cd7b8072c94e 100644
--- a/spec/services/settings/working_days_update_service_spec.rb
+++ b/spec/services/settings/working_days_and_hours_update_service_spec.rb
@@ -27,7 +27,7 @@
require "spec_helper"
require_relative "shared/shared_call_examples"
-RSpec.describe Settings::WorkingDaysUpdateService do
+RSpec.describe Settings::WorkingDaysAndHoursUpdateService do
let(:instance) do
described_class.new(user:)
end
@@ -39,7 +39,7 @@
end
let(:contract_success) { true }
let(:params_contract) do
- instance_double(Settings::WorkingDaysParamsContract,
+ instance_double(Settings::WorkingDaysAndHoursParamsContract,
valid?: params_contract_success,
errors: instance_double(ActiveModel::Error))
end
@@ -55,20 +55,20 @@
# stub a setting definition
allow(Setting)
.to receive(:[])
- .and_call_original
+ .and_call_original
allow(Setting)
.to receive(:[]).with(setting_name)
- .and_return(previous_setting_value)
+ .and_return(previous_setting_value)
allow(Setting)
.to receive(:[]=)
# stub contract
allow(Settings::UpdateContract)
.to receive(:new)
- .and_return(contract)
- allow(Settings::WorkingDaysParamsContract)
+ .and_return(contract)
+ allow(Settings::WorkingDaysAndHoursParamsContract)
.to receive(:new)
- .and_return(params_contract)
+ .and_return(params_contract)
end
describe "#call" do
@@ -87,7 +87,7 @@
expect(WorkPackages::ApplyWorkingDaysChangeJob)
.to have_received(:perform_later)
- .with(user_id: user.id, previous_working_days:, previous_non_working_days:)
+ .with(user_id: user.id, previous_working_days:, previous_non_working_days:)
end
end
diff --git a/spec/services/work_packages/update_ancestors/loader_spec.rb b/spec/services/work_packages/update_ancestors/loader_spec.rb
index 0b4f7c70bd24..8986890fcdbc 100644
--- a/spec/services/work_packages/update_ancestors/loader_spec.rb
+++ b/spec/services/work_packages/update_ancestors/loader_spec.rb
@@ -27,6 +27,17 @@
require "spec_helper"
RSpec.describe WorkPackages::UpdateAncestors::Loader, type: :model do
+ shared_let(:user) { create(:user) }
+ shared_let(:project) { create(:project_with_types) }
+ shared_let(:included_status) { create(:status) }
+ shared_let(:excluded_status) { create(:rejected_status) }
+
+ before_all do
+ set_factory_default(:project_with_types, project)
+ set_factory_default(:status, included_status)
+ set_factory_default(:user, user)
+ end
+
shared_let(:grandgrandparent) do
create(:work_package,
subject: "grandgrandparent")
@@ -223,67 +234,78 @@
end
end
- describe "#descendants_of" do
- def descendants_of_hash(hashed_work_package)
- { "estimated_hours" => nil,
- "id" => hashed_work_package.id,
- "ignore_non_working_days" => false,
- "parent_id" => hashed_work_package.parent_id,
- "remaining_hours" => nil,
- "schedule_manually" => false }
- end
+ def work_package_struct(work_package)
+ attribute_names = WorkPackages::UpdateAncestors::Loader::WorkPackageLikeStruct.members.map(&:to_s)
+ attributes = work_package.attributes.slice(*attribute_names)
+ attributes[:status_excluded_from_totals] = false
+ WorkPackages::UpdateAncestors::Loader::WorkPackageLikeStruct.new(**attributes)
+ end
+ describe "#descendants_of" do
context "for the work_package" do
- it "is its child (as a hash)" do
+ it "is its child (as a struct)" do
expect(instance.descendants_of(work_package))
- .to contain_exactly(descendants_of_hash(child))
+ .to contain_exactly(work_package_struct(child))
+ end
+
+ context "with the child having a status not being excluded from totals calculation" do
+ before do
+ child.update(status: included_status)
+ end
+
+ it "correctly responds true to #included_in_totals_calculation? like a WorkPackage instance" do
+ child = instance.descendants_of(work_package).first
+ expect(child.included_in_totals_calculation?).to be true
+ end
+ end
+
+ context "with the child having a status being excluded from totals calculation" do
+ before do
+ child.update(status: excluded_status)
+ end
+
+ it "correctly responds false to #included_in_totals_calculation? like a WorkPackage instance" do
+ child = instance.descendants_of(work_package).first
+ expect(child.included_in_totals_calculation?).to be false
+ end
end
end
context "for the parent" do
- it "is the work package, its child (as a hash) and its sibling (as a hash)" do
+ it "is the work package, its child (as a struct) and its sibling (as a struct)" do
expect(instance.descendants_of(parent))
- .to contain_exactly(descendants_of_hash(child), work_package, descendants_of_hash(sibling))
+ .to contain_exactly(work_package_struct(child), work_package, work_package_struct(sibling))
end
end
context "for the grandparent" do
- it "is the parent, the work package, its child (as a hash) and its sibling (as a hash)" do
+ it "is the parent, the work package, its child (as a struct) and its sibling (as a struct)" do
expect(instance.descendants_of(grandparent))
- .to contain_exactly(parent, work_package, descendants_of_hash(child), descendants_of_hash(sibling))
+ .to contain_exactly(parent, work_package, work_package_struct(child), work_package_struct(sibling))
end
end
context "for the grandgrandparent (the root)" do
- it "is the complete tree, partly as a hash and partly as the preloaded work packages" do
+ it "is the complete tree, partly as a struct and partly as the preloaded work packages" do
expect(instance.descendants_of(grandgrandparent))
- .to contain_exactly(descendants_of_hash(grandparent_sibling), grandparent, parent, work_package,
- descendants_of_hash(child), descendants_of_hash(sibling))
+ .to contain_exactly(work_package_struct(grandparent_sibling), grandparent, parent, work_package,
+ work_package_struct(child), work_package_struct(sibling))
end
end
end
describe "#children_of" do
- def children_of_hash(hashed_work_package)
- { "estimated_hours" => nil,
- "id" => hashed_work_package.id,
- "ignore_non_working_days" => false,
- "parent_id" => hashed_work_package.parent_id,
- "remaining_hours" => nil,
- "schedule_manually" => false }
- end
-
context "for the work_package" do
- it "is its child (as a hash)" do
+ it "is its child (as a struct)" do
expect(instance.children_of(work_package))
- .to contain_exactly(children_of_hash(child))
+ .to contain_exactly(work_package_struct(child))
end
end
context "for the parent" do
- it "is the work package and its sibling (as a hash)" do
+ it "is the work package and its sibling (as a struct)" do
expect(instance.children_of(parent))
- .to contain_exactly(work_package, children_of_hash(sibling))
+ .to contain_exactly(work_package, work_package_struct(sibling))
end
end
@@ -295,9 +317,9 @@ def children_of_hash(hashed_work_package)
end
context "for the grandgrandparent" do
- it "is the grandparent and its sibling (as a hash)" do
+ it "is the grandparent and its sibling (as a struct)" do
expect(instance.children_of(grandgrandparent))
- .to contain_exactly(children_of_hash(grandparent_sibling), grandparent)
+ .to contain_exactly(work_package_struct(grandparent_sibling), grandparent)
end
end
end
diff --git a/spec/services/work_packages/update_ancestors_service_spec.rb b/spec/services/work_packages/update_ancestors_service_spec.rb
index b549fca80e5b..3ea159cd7a6d 100644
--- a/spec/services/work_packages/update_ancestors_service_spec.rb
+++ b/spec/services/work_packages/update_ancestors_service_spec.rb
@@ -34,16 +34,11 @@
shared_association_default(:priority) { create(:priority) }
shared_association_default(:open_status, factory_name: :status) { create(:status, name: "Open", default_done_ratio: 0) }
shared_let(:closed_status) { create(:closed_status, name: "Closed", default_done_ratio: 100) }
+ shared_let(:rejected_status) { create(:rejected_status, default_done_ratio: 20) }
shared_let(:user) { create(:user) }
- let(:estimated_hours) { [nil, nil, nil] }
- let(:done_ratios) { [0, 0, 0] }
- let(:statuses) { %i(open open open) }
- let(:aggregate_done_ratio) { 0.0 }
- let(:ignore_non_working_days) { [false, false, false] }
-
# In order to have dependent values computed, this leverages
- # the SetAttributesService to mimick how attributes are set
+ # the SetAttributesService to mimic how attributes are set
# on work packages prior to the UpdateAncestorsService being
# executed.
def set_attributes_on(work_package, attributes)
@@ -54,82 +49,81 @@ def set_attributes_on(work_package, attributes)
.call(attributes)
end
- describe "done_ratio/estimated_hours/remaining_hours propagation" do
- context "when setting the status of a work package" do
- context 'when using the "status-based" % complete mode',
- with_settings: { work_package_done_ratio: "status" } do
- def call_update_ancestors_service(work_package)
- changed_attributes = work_package.changes.keys.map(&:to_sym)
- described_class.new(user:, work_package:)
- .call(changed_attributes)
- end
+ def call_update_ancestors_service(work_package)
+ changed_attributes = work_package.changes.keys.map(&:to_sym)
+ described_class.new(user:, work_package:)
+ .call(changed_attributes)
+ end
- context "with both parent and children having estimated hours set" do
- shared_let(:parent) do
- create(:work_package,
- subject: "parent",
- estimated_hours: 10.0,
- remaining_hours: 10.0,
- derived_estimated_hours: 15.0,
- derived_remaining_hours: 15.0,
- status: open_status)
- end
- shared_let(:child) do
- create(:work_package,
- subject: "child",
- parent:,
- estimated_hours: 5.0,
- remaining_hours: 5.0,
- status: open_status)
- end
+ describe "work, remaining work, and % complete propagation" do
+ context 'when using the "status-based" progress calculation mode',
+ with_settings: { work_package_done_ratio: "status" } do
+ context "with both parent and children having work set" do
+ shared_let_work_packages(<<~TABLE)
+ hierarchy | status | work | ∑ work | remaining work | ∑ remaining work | % complete | ∑ % complete
+ parent | Open | 10h | 15h | 10h | 15h | 0% | 0%
+ child | Open | 5h | | 5h | | 0% |
+ TABLE
- context "when changing child status to a status with a default done ratio" do
- %i[status status_id].each do |field|
- context "with the #{field} field" do
- it "recomputes child remaining work and updates ancestors total % complete accordingly" do
- value =
- case field
- when :status then closed_status
- when :status_id then closed_status.id
- end
- set_attributes_on(child, field => value)
- call_update_ancestors_service(child)
-
- expect_work_packages([parent, child], <<~TABLE)
- | subject | work | total work | remaining work | total remaining work | % complete | total % complete |
- | parent | 10h | 15h | 10h | 10h | 0% | 33% |
- | child | 5h | | 0h | | 100% | |
- TABLE
- end
+ context "when changing child status to a status with a default % complete ratio" do
+ %i[status status_id].each do |field|
+ context "with the #{field} field" do
+ it "recomputes child remaining work and updates ancestors total % complete accordingly" do
+ value =
+ case field
+ when :status then closed_status
+ when :status_id then closed_status.id
+ end
+ set_attributes_on(child, field => value)
+ call_update_ancestors_service(child)
+
+ expect_work_packages([parent, child], <<~TABLE)
+ | subject | status | work | ∑ work | remaining work | ∑ remaining work | % complete | ∑ % complete |
+ | parent | Open | 10h | 15h | 10h | 10h | 0% | 33% |
+ | child | Closed | 5h | | 0h | | 100% | |
+ TABLE
end
end
end
end
- context "with parent having nothing set, and 2 children having values set (bug #54179)" do
- let_work_packages(<<~TABLE)
- hierarchy | status | work | ∑ work | remaining work | ∑ remaining work | % complete | ∑ % complete
- parent | Open | | 15h | | 10h | 0% | 33%
- child1 | Open | 10h | | 10h | | 0% |
- child2 | Closed | 5h | | 0h | | 100% |
- TABLE
+ context "when changing child status to a status excluded from totals calculation" do
+ before do
+ set_attributes_on(child, status: rejected_status)
+ call_update_ancestors_service(child)
+ end
- context "when changing children to all have 100% complete" do
- before do
- set_attributes_on(child1, status: closed_status)
- call_update_ancestors_service(child1)
- end
+ it "still recomputes child remaining work and updates ancestors total % complete excluding it" do
+ expect_work_packages([parent, child], <<~TABLE)
+ | subject | status | work | ∑ work | remaining work | ∑ remaining work | % complete | ∑ % complete |
+ | parent | Open | 10h | 10h | 10h | 10h | 0% | 0% |
+ | child | Rejected | 5h | | 4h | | 20% | |
+ TABLE
+ end
+ end
+ end
- it "sets parent total % complete to 100% and its total remaining work to 0h, " \
- "and computes totals for the updated children too" do
- table_work_packages.map(&:reload)
- expect_work_packages(table_work_packages, <<~TABLE)
- hierarchy | status | work | ∑ work | remaining work | ∑ remaining work | % complete | ∑ % complete
- parent | Open | | 15h | | 0h | 0% | 100%
- child1 | Closed | 10h | | 0h | | 100% |
- child2 | Closed | 5h | | 0h | | 100% |
- TABLE
- end
+ context "with parent having nothing set, and 2 children having values set (bug #54179)" do
+ shared_let_work_packages(<<~TABLE)
+ hierarchy | status | work | ∑ work | remaining work | ∑ remaining work | % complete | ∑ % complete
+ parent | Open | | 15h | | 10h | 0% | 33%
+ child1 | Open | 10h | | 10h | | 0% |
+ child2 | Closed | 5h | | 0h | | 100% |
+ TABLE
+
+ context "when changing children to all have 100% complete" do
+ before do
+ set_attributes_on(child1, status: closed_status)
+ call_update_ancestors_service(child1)
+ end
+
+ it "sets parent total % complete to 100% and its total remaining work to 0h" do
+ expect_work_packages(table_work_packages, <<~TABLE)
+ hierarchy | status | work | ∑ work | remaining work | ∑ remaining work | % complete | ∑ % complete
+ parent | Open | | 15h | | 0h | 0% | 100%
+ child1 | Closed | 10h | | 0h | | 100% |
+ child2 | Closed | 5h | | 0h | | 100% |
+ TABLE
end
end
end
@@ -137,459 +131,228 @@ def call_update_ancestors_service(work_package)
context "for the new ancestor chain" do
shared_examples "attributes of parent having children" do
- before do
- children
- end
-
it "is a success" do
expect(subject)
.to be_success
end
- it "updated one work package - the parent" do
+ it "updates one work package - the parent" do
expect(subject.dependent_results.map(&:result))
.to contain_exactly(parent)
end
- it "has the expected derived done ratio" do
+ it "has the expected total % complete" do
expect(subject.dependent_results.first.result.derived_done_ratio)
- .to eq aggregate_done_ratio
+ .to eq expected_total_p_complete
end
- it "has the expected derived estimated_hours" do
+ it "has the expected total work" do
expect(subject.dependent_results.first.result.derived_estimated_hours)
- .to eq aggregate_estimated_hours
+ .to eq expected_total_work
end
- it "has the expected derived remaining_hours" do
+ it "has the expected total remaining work" do
expect(subject.dependent_results.first.result.derived_remaining_hours)
- .to eq aggregate_remaining_hours
+ .to eq expected_total_remaining_work
end
end
- context "when on field-based mode for % complete" do
- let(:children) do
- (statuses.size - 1).downto(0).map do |i|
- create(:work_package,
- parent:,
- subject: "child #{i}",
- estimated_hours: estimated_hours[i],
- remaining_hours: remaining_hours[i],
- ignore_non_working_days:)
- end
+ shared_context "when work is changed" do
+ subject do
+ # On work-based mode, changing estimated_hours
+ # entails done_ratio also changing when going
+ # through the SetAttributesService
+ described_class
+ .new(user:,
+ work_package: child1)
+ .call(%i(estimated_hours done_ratio))
end
+ end
- shared_let(:parent) { create(:work_package, subject: "parent", status: open_status) }
-
- context "when estimated_hours is changed" do
- subject do
- # On field-based mode, changing estimated_hours
- # entails done_ratio also changing when going
- # through the SetAttributesService
- described_class
- .new(user:,
- work_package: children.first)
- .call(%i(estimated_hours done_ratio))
- end
-
- context "with no estimated hours and no progress" do
- let(:estimated_hours) { [nil, nil, nil] }
- let(:remaining_hours) { [nil, nil, nil] }
-
- it "is a success" do
- expect(subject)
- .to be_success
- end
-
- it "does not update the parent" do
- expect(subject.dependent_results)
- .to be_empty
- end
- end
+ shared_context "when remaining work is changed" do
+ subject do
+ # On work-based mode, changing remaining work
+ # entails % complete also changing when going
+ # through the SetAttributesService
+ described_class
+ .new(user:,
+ work_package: child1)
+ .call(%i(remaining_hours done_ratio))
+ end
+ end
- context "with all tasks having estimated hours and some having progress done already" do
- it_behaves_like "attributes of parent having children" do
- let(:estimated_hours) do
- [10.0, 10.0, 10.0]
- end
- let(:remaining_hours) do
- [0.0, 0.0, 10.0]
- end
+ context "without any work or % complete being set" do
+ shared_let_work_packages(<<~TABLE)
+ hierarchy | work | remaining work | % complete
+ parent | | |
+ child1 | | |
+ child2 | | |
+ child3 | | |
+ TABLE
- let(:aggregate_estimated_hours) do
- 30.0
- end
- let(:aggregate_remaining_hours) do
- 10.0
- end
- let(:aggregate_done_ratio) do
- 67
- end
- end
+ for_each_context "when work is changed",
+ "when remaining work is changed" do
+ it "is a success" do
+ expect(subject)
+ .to be_success
end
- context "with all tasks having estimated hours and all having progress done already" do
- it_behaves_like "attributes of parent having children" do
- let(:estimated_hours) do
- [10.0, 10.0, 10.0]
- end
- let(:remaining_hours) do
- [2.5, 2.5, 10.0]
- end
-
- let(:aggregate_estimated_hours) do
- 30.0
- end
- let(:aggregate_remaining_hours) do
- 15.0
- end
- let(:aggregate_done_ratio) do
- 50
- end
- end
+ it "does not update the parent" do
+ expect(subject.dependent_results)
+ .to be_empty
end
+ end
+ end
- context "with all tasks having estimated hours and no tasks having any remaining hours" do
- it_behaves_like "attributes of parent having children" do
- let(:estimated_hours) do
- [10.0, 2.0, 3.0]
- end
- let(:remaining_hours) do
- [0.0, 0.0, 0.0]
- end
+ context "with all children tasks having work and remaining work set" do
+ shared_let_work_packages(<<~TABLE)
+ hierarchy | work | remaining work | % complete
+ parent | | |
+ child1 | 10h | 0h | 100%
+ child2 | 10h | 0h | 100%
+ child3 | 10h | 10h | 0%
+ TABLE
- let(:aggregate_estimated_hours) do
- 15.0
- end
- let(:aggregate_remaining_hours) do
- 0.0
- end
- let(:aggregate_done_ratio) do
- 100
- end
+ for_each_context "when work is changed",
+ "when remaining work is changed" do
+ it_behaves_like "attributes of parent having children" do
+ let(:expected_total_work) do
+ 30.0
end
- end
-
- context "with all tasks having estimated hours and no tasks having progress set" do
- it_behaves_like "attributes of parent having children" do
- let(:estimated_hours) do
- [10.0, 2.0, 3.0]
- end
- let(:remaining_hours) do
- [nil, nil, nil]
- end
-
- let(:aggregate_estimated_hours) do
- 15.0
- end
- let(:aggregate_remaining_hours) do
- nil
- end
- let(:aggregate_done_ratio) do
- nil
- end
+ let(:expected_total_remaining_work) do
+ 10.0
end
- end
-
- context "with some tasks having estimated hours and none having progress set" do
- it_behaves_like "attributes of parent having children" do
- let(:estimated_hours) do
- [10.0, nil, nil]
- end
- let(:remaining_hours) do
- [nil, nil, nil]
- end
-
- let(:aggregate_estimated_hours) do
- 10.0
- end
- let(:aggregate_remaining_hours) do
- nil
- end
- let(:aggregate_done_ratio) do
- nil
- end
+ let(:expected_total_p_complete) do
+ 67
end
end
+ end
+ end
- context "with some tasks having estimated hours and those that do also having progress done" do
- it_behaves_like "attributes of parent having children" do
- let(:estimated_hours) do
- [10.0, nil, nil]
- end
- let(:remaining_hours) do
- [2.5, nil, nil]
- end
-
- let(:aggregate_estimated_hours) do
- 10.0
- end
- let(:aggregate_remaining_hours) do
- 2.5
- end
- let(:aggregate_done_ratio) do
- 75
- end
- end
- end
+ context "with all children tasks having work and remaining work set (second example)" do
+ shared_let_work_packages(<<~TABLE)
+ hierarchy | work | remaining work | % complete
+ parent | | |
+ child1 | 10h | 2.5h | 75%
+ child2 | 10h | 2.5h | 75%
+ child3 | 10h | 10h | 0%
+ TABLE
- context "with the parent having estimated hours and progress" do
- shared_let(:parent) do
- create(:work_package,
- subject: "parent",
- estimated_hours: 10.0,
- remaining_hours: 5.0)
+ for_each_context "when work is changed",
+ "when remaining work is changed" do
+ it_behaves_like "attributes of parent having children" do
+ let(:expected_total_work) do
+ 30.0
end
-
- context "and some tasks having estimated hours and some progress" do
- it_behaves_like "attributes of parent having children" do
- let(:estimated_hours) do
- [10.0, nil, nil]
- end
- let(:remaining_hours) do
- [2.5, nil, nil]
- end
-
- # Parent's estimated and remaining hours are taken into account
- let(:aggregate_estimated_hours) do
- 20.0
- end
- let(:aggregate_remaining_hours) do
- 7.5
- end
- let(:aggregate_done_ratio) do
- 63
- end
- end
+ let(:expected_total_remaining_work) do
+ 15.0
end
-
- context "and no tasks having estimated hours or progress" do
- it_behaves_like "attributes of parent having children" do
- let(:estimated_hours) do
- [nil, nil, nil]
- end
- let(:remaining_hours) do
- [nil, nil, nil]
- end
-
- # Parent's estimated hours and remaining hours become the aggregated values
- let(:aggregate_estimated_hours) do
- 10.0
- end
- let(:aggregate_remaining_hours) do
- 5.0
- end
- let(:aggregate_done_ratio) do
- 50
- end
- end
+ let(:expected_total_p_complete) do
+ 50
end
end
end
+ end
- context "when remaining_hours is changed" do
- subject do
- # On field-based mode, changing remaining_hours
- # entails done_ratio also changing when going
- # through the SetAttributesService
- described_class
- .new(user:,
- work_package: children.first)
- .call(%i(remaining_hours done_ratio))
- end
-
- context "with no estimated hours and no progress" do
- let(:estimated_hours) { [nil, nil, nil] }
- let(:remaining_hours) { [nil, nil, nil] }
- # let(:statuses) { %i(open open open) }
+ context "with all children tasks having work set to positive value, and having remaining work set to 0h" do
+ shared_let_work_packages(<<~TABLE)
+ hierarchy | work | remaining work | % complete
+ parent | | |
+ child1 | 10h | 0h | 100%
+ child2 | 2h | 0h | 100%
+ child3 | 3h | 0h | 100%
+ TABLE
- it "is a success" do
- expect(subject)
- .to be_success
+ for_each_context "when work is changed",
+ "when remaining work is changed" do
+ it_behaves_like "attributes of parent having children" do
+ let(:expected_total_work) do
+ 15.0
end
-
- it "does not update the parent" do
- expect(subject.dependent_results)
- .to be_empty
+ let(:expected_total_remaining_work) do
+ 0.0
end
- end
-
- context "with all tasks having estimated hours and some having progress done already" do
- it_behaves_like "attributes of parent having children" do
- let(:estimated_hours) do
- [10.0, 10.0, 10.0]
- end
- let(:remaining_hours) do
- [0.0, 0.0, 10.0]
- end
-
- let(:aggregate_estimated_hours) do
- 30.0
- end
- let(:aggregate_remaining_hours) do
- 10.0
- end
- let(:aggregate_done_ratio) do
- 67
- end
+ let(:expected_total_p_complete) do
+ 100
end
end
+ end
+ end
- context "with all tasks having estimated hours and all having progress done already" do
- it_behaves_like "attributes of parent having children" do
- let(:estimated_hours) do
- [10.0, 10.0, 10.0]
- end
- let(:remaining_hours) do
- [2.5, 2.5, 10.0]
- end
+ context "with some children tasks having work and remaining work set" do
+ shared_let_work_packages(<<~TABLE)
+ hierarchy | work | remaining work | % complete
+ parent | | |
+ child1 | 10h | 2.5h | 75%
+ child2 | | |
+ child3 | | |
+ TABLE
- let(:aggregate_estimated_hours) do
- 30.0
- end
- let(:aggregate_remaining_hours) do
- 15.0
- end
- let(:aggregate_done_ratio) do
- 50
- end
+ for_each_context "when work is changed",
+ "when remaining work is changed" do
+ it_behaves_like "attributes of parent having children" do
+ let(:expected_total_work) do
+ 10.0
end
- end
-
- context "with all tasks having estimated hours and no tasks having remaining hours" do
- it_behaves_like "attributes of parent having children" do
- let(:estimated_hours) do
- [10.0, 2.0, 3.0]
- end
- let(:remaining_hours) do
- [0.0, 0.0, 0.0]
- end
-
- let(:aggregate_estimated_hours) do
- 15.0
- end
- let(:aggregate_remaining_hours) do
- 0.0
- end
- let(:aggregate_done_ratio) do
- 100
- end
+ let(:expected_total_remaining_work) do
+ 2.5
end
- end
-
- context "with all tasks having estimated hours and no tasks having progress set" do
- it_behaves_like "attributes of parent having children" do
- let(:estimated_hours) do
- [10.0, 2.0, 3.0]
- end
- let(:remaining_hours) do
- [nil, nil, nil]
- end
-
- let(:aggregate_estimated_hours) do
- 15.0
- end
- let(:aggregate_remaining_hours) do
- nil
- end
- let(:aggregate_done_ratio) do
- nil
- end
+ let(:expected_total_p_complete) do
+ 75
end
end
+ end
+ end
- context "with some tasks having estimated hours and none having progress set" do
- it_behaves_like "attributes of parent having children" do
- let(:estimated_hours) do
- [10.0, nil, nil]
- end
- let(:remaining_hours) do
- [nil, nil, nil]
- end
+ context "with the parent having work and % complete set " \
+ "and some children tasks having work and % complete set" do
+ shared_let_work_packages(<<~TABLE)
+ hierarchy | work | remaining work | % complete
+ parent | 10h | 5h | 50%
+ child1 | 10h | 2.5h | 75%
+ child2 | | |
+ child3 | | |
+ TABLE
- let(:aggregate_estimated_hours) do
- 10.0
- end
- let(:aggregate_remaining_hours) do
- nil
- end
- let(:aggregate_done_ratio) do
- nil
- end
+ for_each_context "when work is changed",
+ "when remaining work is changed" do
+ it_behaves_like "attributes of parent having children" do
+ # Parent's work and remaining work are taken into account
+ let(:expected_total_work) do
+ 20.0
end
- end
-
- context "with some tasks having estimated hours and those that do also having progress done" do
- it_behaves_like "attributes of parent having children" do
- let(:estimated_hours) do
- [10.0, nil, nil]
- end
- let(:remaining_hours) do
- [2.5, nil, nil]
- end
-
- let(:aggregate_estimated_hours) do
- 10.0
- end
- let(:aggregate_remaining_hours) do
- 2.5
- end
- let(:aggregate_done_ratio) do
- 75
- end
+ let(:expected_total_remaining_work) do
+ 7.5
+ end
+ let(:expected_total_p_complete) do
+ 63
end
end
+ end
+ end
- context "with the parent having estimated hours and progress" do
- shared_let(:parent) do
- create(:work_package,
- subject: "parent",
- estimated_hours: 10.0,
- remaining_hours: 5.0)
- end
+ context "with the parent having work and % complete set " \
+ "and no children tasks having work or % complete set" do
+ shared_let_work_packages(<<~TABLE)
+ hierarchy | work | remaining work | % complete
+ parent | 10h | 5h | 50%
+ child1 | | |
+ child2 | | |
+ child3 | | |
+ TABLE
- context "and some tasks having estimated hours and some progress" do
- it_behaves_like "attributes of parent having children" do
- let(:estimated_hours) do
- [10.0, nil, nil]
- end
- let(:remaining_hours) do
- [2.5, nil, nil]
- end
-
- # Parent's estimated and remaining hours are taken into account
- let(:aggregate_estimated_hours) do
- 20.0
- end
- let(:aggregate_remaining_hours) do
- 7.5
- end
- let(:aggregate_done_ratio) do
- 63
- end
- end
+ for_each_context "when work is changed",
+ "when remaining work is changed" do
+ it_behaves_like "attributes of parent having children" do
+ # Parent's work and remaining work become the total values
+ let(:expected_total_work) do
+ 10.0
end
-
- context "and no tasks having estimated hours or progress" do
- it_behaves_like "attributes of parent having children" do
- let(:estimated_hours) do
- [nil, nil, nil]
- end
- let(:remaining_hours) do
- [nil, nil, nil]
- end
-
- # Parent's estimated hours and remaining hours become the aggregated values
- let(:aggregate_estimated_hours) do
- 10.0
- end
- let(:aggregate_remaining_hours) do
- 5.0
- end
- let(:aggregate_done_ratio) do
- 50
- end
- end
+ let(:expected_total_remaining_work) do
+ 5.0
+ end
+ let(:expected_total_p_complete) do
+ 50
end
end
end
@@ -597,37 +360,13 @@ def call_update_ancestors_service(work_package)
end
context "for the previous ancestors" do
- shared_let(:sibling_estimated_hours) { 7.0 }
- shared_let(:sibling_remaining_hours) { 3.5 }
- shared_let(:parent_estimated_hours) { 3.0 }
- shared_let(:grandparent_estimated_hours) { 3.0 }
- shared_let(:grandparent_remaining_hours) { 1.5 }
-
- shared_let(:grandparent) do
- create(:work_package,
- subject: "grandparent",
- estimated_hours: grandparent_estimated_hours,
- remaining_hours: grandparent_remaining_hours)
- end
- shared_let(:parent) do
- create(:work_package,
- subject: "parent",
- estimated_hours: parent_estimated_hours,
- parent: grandparent)
- end
- shared_let(:sibling) do
- create(:work_package,
- subject: "sibling",
- parent:,
- estimated_hours: sibling_estimated_hours,
- remaining_hours: sibling_remaining_hours)
- end
-
- shared_let(:work_package) do
- create(:work_package,
- subject: "subject - loses its parent",
- parent:)
- end
+ shared_let_work_packages(<<~TABLE)
+ hierarchy | work | remaining work | % complete
+ grandparent | 3h | 1.5h | 50%
+ parent | 3h | 0h | 100%
+ work package | | |
+ sibling | 7h | 3.5h | 50%
+ TABLE
subject do
work_package.parent = nil
@@ -644,93 +383,25 @@ def call_update_ancestors_service(work_package)
.to be_success
end
+ it "updates the totals of the ancestors" do
+ subject
+ expect_work_packages([grandparent, parent, sibling, work_package], <<~TABLE)
+ hierarchy | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete
+ grandparent | 3h | 1.5h | 50% | 13h | 5h | 62%
+ parent | 3h | 0h | 100% | 10h | 3.5h | 65%
+ sibling | 7h | 3.5h | 50% | | |
+ work package | | | | | |
+ TABLE
+ end
+
it "returns the former ancestors in the dependent results" do
expect(subject.dependent_results.map(&:result))
.to contain_exactly(parent, grandparent)
end
-
- it "updates the derived_done_ratio, derived_estimated_hours, and derived_remaining_hours of the former parent" do
- expect do
- subject
- parent.reload
- end
- .to change(parent, :derived_done_ratio).to(65) # 6.5h derived_work_done / 10.0h derived_estimated_hours
- .and change(parent, :derived_estimated_hours).to(parent_estimated_hours + sibling_estimated_hours)
- .and change(parent, :derived_remaining_hours).to(sibling_remaining_hours)
- end
-
- it "updates the derived_done_ratio, derived_estimated_hours, and derived_remaining_hours of the former grandparent" do
- expect do
- subject
- grandparent.reload
- end
- .to change(grandparent, :derived_done_ratio).to(62) # 8.0h derived_work_done / 13.0h derived_estimated_hours
- .and change(grandparent, :derived_estimated_hours).to(grandparent_estimated_hours +
- parent_estimated_hours +
- sibling_estimated_hours)
- .and change(grandparent, :derived_remaining_hours).to(sibling_remaining_hours +
- grandparent_remaining_hours)
- end
end
context "for new ancestors" do
- shared_let(:estimated_hours) { 7.0 }
- shared_let(:remaining_hours) { 3.5 }
- shared_let(:parent_estimated_hours) { 3.0 }
- shared_let(:parent_remaining_hours) { 1.5 }
-
- shared_let(:grandparent) do
- create(:work_package,
- subject: "grandparent")
- end
- shared_let(:parent) do
- create(:work_package,
- subject: "parent",
- estimated_hours: parent_estimated_hours,
- remaining_hours: parent_remaining_hours,
- parent: grandparent)
- end
- shared_let(:work_package) do
- create(:work_package,
- subject: "subject - gains a new parent and grandparent",
- estimated_hours:,
- remaining_hours:)
- end
-
- shared_examples_for "updates the attributes within the new hierarchy" do
- it "is successful" do
- expect(subject)
- .to be_success
- end
-
- it "returns the new ancestors in the dependent results" do
- expect(subject.dependent_results.map(&:result))
- .to contain_exactly(parent, grandparent)
- end
-
- it "updates the derived_done_ratio, derived_estimated_hours, and derived_remaining_hours of the new parent" do
- expect do
- subject
- parent.reload
- end
- .to change(parent, :derived_done_ratio).to(50) # 5.0h derived_work_done / 10.0h derived_estimated_hours
- .and change(parent, :derived_estimated_hours).to(parent_estimated_hours + estimated_hours)
- .and change(parent, :derived_remaining_hours).to(parent_remaining_hours + remaining_hours)
- end
-
- it "updates the derived_done_ratio, derived_estimated_hours, and derived_remaining_hours " \
- "of the new grandparent" do
- expect do
- subject
- grandparent.reload
- end
- .to change(grandparent, :derived_done_ratio).to(50) # 5.0h derived_work_done / 10.0h derived_estimated_hours
- .and change(grandparent, :derived_estimated_hours).to(parent_estimated_hours + estimated_hours)
- .and change(grandparent, :derived_remaining_hours).to(parent_remaining_hours + remaining_hours)
- end
- end
-
- context "if setting the parent" do
+ shared_context "if setting the parent" do
subject do
work_package.parent = parent
work_package.save!
@@ -740,11 +411,9 @@ def call_update_ancestors_service(work_package)
work_package:)
.call(%i(parent))
end
-
- it_behaves_like "updates the attributes within the new hierarchy"
end
- context "if setting the parent_id" do
+ shared_context "if setting the parent_id" do
subject do
work_package.parent_id = parent.id
work_package.save!
@@ -754,59 +423,61 @@ def call_update_ancestors_service(work_package)
work_package:)
.call(%i(parent_id))
end
+ end
+
+ shared_let_work_packages(<<~TABLE)
+ hierarchy | work | remaining work | % complete
+ grandparent | | |
+ parent | 3h | 1.5h | 50%
+ work package | 7h | 3.5h | 50%
+ TABLE
+
+ for_each_context "if setting the parent",
+ "if setting the parent_id" do
+ it "is successful" do
+ expect(subject)
+ .to be_success
+ end
+
+ it "returns the new ancestors in the dependent results" do
+ expect(subject.dependent_results.map(&:result))
+ .to contain_exactly(parent, grandparent)
+ end
- it_behaves_like "updates the attributes within the new hierarchy"
+ it "updates the totals of the ancestors" do
+ subject
+ expect_work_packages([grandparent, parent, work_package], <<~TABLE)
+ hierarchy | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete
+ grandparent | | | | 10h | 5h | 50%
+ parent | 3h | 1.5h | 50% | 10h | 5h | 50%
+ work package | 7h | 3.5h | 50% | | |
+ TABLE
+ end
end
end
context "with old and new parent having a common ancestor" do
- shared_let(:estimated_hours) { 7.0 }
- shared_let(:remaining_hours) { 3.5 }
- shared_let(:new_estimated_hours) { 10.0 }
- shared_let(:new_remaining_hours) { 2 }
-
- shared_let(:grandparent) do
- create(:work_package,
- subject: "common grandparent",
- derived_done_ratio: 50, # two children having [done_ratio, 0]
- derived_estimated_hours: estimated_hours,
- derived_remaining_hours: remaining_hours)
- end
- shared_let(:old_parent) do
- create(:work_package,
- subject: "old parent",
- parent: grandparent,
- derived_done_ratio: 50,
- derived_estimated_hours: estimated_hours,
- derived_remaining_hours: remaining_hours)
- end
- shared_let(:new_parent) do
- create(:work_package,
- subject: "new parent",
- parent: grandparent)
- end
- shared_let(:work_package) do
- create(:work_package,
- subject: "subject - parent changes from old parent to new parent, same grandparent",
- parent: old_parent,
- estimated_hours:,
- remaining_hours:)
- end
+ # work_package's parent will change from old parent to new parent, same grandparent
+ shared_let_work_packages(<<~TABLE)
+ hierarchy | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete
+ grandparent | | | | 7h | 3.5h | 50%
+ old parent | | | | 7h | 3.5h | 50%
+ work package | 7h | 3.5h | 50% | | |
+ new parent | | | | | |
+ TABLE
subject do
- work_package.parent = new_parent
# In this test case, done_ratio, derived_estimated_hours, and
- # derived_remaining_hours would not inherently change on grandparent.
- # However, if work_package has siblings then changing its parent could
- # cause done_ratio, derived_estimated_hours, and/or
- # derived_remaining_hours on grandparent to inherently change. To verify
- # that grandparent can be properly updated in that case without making
- # this test dependent on the implementation details of the calculations,
- # done_ratio, derived_estimated_hours, and derived_remaining_hours are
- # forced to change at the same time as the parent.
+ # derived_remaining_hours would not inherently change on grandparent
+ # if work package keeps the same progress values.
+ #
+ # To verify that grandparent can be properly updated in this scenario,
+ # work and remaining work are also changed on the work package to force
+ # grandparent totals to be updated.
set_attributes_on(work_package,
- estimated_hours: new_estimated_hours,
- remaining_hours: new_remaining_hours)
+ parent: new_parent,
+ estimated_hours: 10,
+ remaining_hours: 2)
work_package.save!
described_class
@@ -820,49 +491,29 @@ def call_update_ancestors_service(work_package)
.to be_success
end
+ it "updates the totals of the new parent and the former parent" do
+ subject
+ expect_work_packages([grandparent, old_parent, new_parent, work_package], <<~TABLE)
+ hierarchy | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete
+ grandparent | | | | 10h | 2h | 80%
+ old parent | | | | | |
+ new parent | | | | 10h | 2h | 80%
+ work package | 10h | 2h | 80% | | |
+ TABLE
+ end
+
it "returns both the former and new ancestors in the dependent results without duplicates" do
expect(subject.dependent_results.map(&:result))
.to contain_exactly(new_parent, grandparent, old_parent)
end
-
- it "updates the derived_done_ratio, derived_estimated_hours, and derived_remaining_hours " \
- "of the former parent to nil" do
- expect do
- subject
- old_parent.reload
- end
- .to change(old_parent, :derived_done_ratio).to(nil)
- .and change(old_parent, :derived_estimated_hours).to(nil)
- .and change(old_parent, :derived_remaining_hours).to(nil)
- end
-
- it "updates the derived_done_ratio, derived_estimated_hours, and derived_remaining_hours of the new parent" do
- expect do
- subject
- new_parent.reload
- end
- .to change(new_parent, :derived_done_ratio).to(80)
- .and change(new_parent, :derived_estimated_hours).to(new_estimated_hours)
- .and change(new_parent, :derived_remaining_hours).to(new_remaining_hours)
- end
-
- it "updates the derived_done_ratio, derived_estimated_hours, and derived_remaining_hours of the grandparent" do
- expect do
- subject
- grandparent.reload
- end
- .to change(grandparent, :derived_done_ratio).to(80)
- .and change(grandparent, :derived_estimated_hours).to(new_estimated_hours)
- .and change(grandparent, :derived_remaining_hours).to(new_remaining_hours)
- end
end
end
describe "work propagation" do
- shared_let(:parent) { create(:work_package, subject: "parent") }
- shared_let(:child) { create(:work_package, subject: "child", parent:) }
-
context "when setting work of a work package having children without any work value" do
+ shared_let(:parent) { create(:work_package, subject: "parent") }
+ shared_let(:child) { create(:work_package, subject: "child", parent:) }
+
before do
parent.estimated_hours = 2.0
end
@@ -1050,7 +701,7 @@ def call_update_ancestors_service(work_package)
end
end
- describe "done_ratio propagation" do
+ describe "% complete propagation" do
shared_let(:parent) { create(:work_package, subject: "parent") }
context "given child with work, when remaining work being set on parent" do
@@ -1096,6 +747,52 @@ def call_update_ancestors_service(work_package)
TABLE
end
end
+
+ context "given child becomes excluded from totals calculation because of its status changed to rejected" do
+ shared_let_work_packages(<<~TABLE)
+ hierarchy | status | work | ∑ work | remaining work | ∑ remaining work | % complete | ∑ % complete
+ parent | Open | 10h | 12h | 1h | 8h | 90% | 33%
+ child | Open | 2h | | 7h | | 29% |
+ TABLE
+
+ subject(:call_result) do
+ set_attributes_on(child, status: rejected_status)
+ call_update_ancestors_service(child)
+ end
+
+ it "computes parent totals excluding the child from calculations accordingly" do
+ expect(call_result).to be_success
+ updated_work_packages = call_result.all_results
+ expect_work_packages(updated_work_packages, <<~TABLE)
+ hierarchy | status | work | ∑ work | remaining work | ∑ remaining work | % complete | ∑ % complete
+ parent | Open | 10h | 10h | 1h | 1h | 90% | 90%
+ child | Rejected | 2h | | 7h | | 29% |
+ TABLE
+ end
+ end
+
+ context "given child is no longer excluded from totals calculation because of its status changed from rejected" do
+ shared_let_work_packages(<<~TABLE)
+ hierarchy | status | work | ∑ work | remaining work | ∑ remaining work | % complete | ∑ % complete
+ parent | Open | 10h | 10h | 1h | 1h | 90% | 90%
+ child | Rejected | 2h | | 7h | | 29% |
+ TABLE
+
+ subject(:call_result) do
+ set_attributes_on(child, status: open_status)
+ call_update_ancestors_service(child)
+ end
+
+ it "computes parent totals excluding the child from calculations accordingly" do
+ expect(call_result).to be_success
+ updated_work_packages = call_result.all_results
+ expect_work_packages(updated_work_packages, <<~TABLE)
+ hierarchy | status | work | ∑ work | remaining work | ∑ remaining work | % complete | ∑ % complete
+ parent | Open | 10h | 12h | 1h | 8h | 90% | 33%
+ child | Open | 2h | | 7h | | 29% |
+ TABLE
+ end
+ end
end
describe "ignore_non_working_days propagation" do
diff --git a/spec/support/for_each_context.rb b/spec/support/for_each_context.rb
new file mode 100644
index 000000000000..78fdee1f77d7
--- /dev/null
+++ b/spec/support/for_each_context.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+#-- copyright
+# OpenProject is an open source project management software.
+# Copyright (C) 2012-2024 the OpenProject GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version 3.
+#
+# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
+# Copyright (C) 2006-2013 Jean-Philippe Lang
+# Copyright (C) 2010-2013 the ChiliProject Team
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# See COPYRIGHT and LICENSE files for more details.
+#++
+
+module RSpecOpExt
+ module ForEachContext
+ # Runs the same example group multiple times: once for each given named
+ # context.
+ #
+ # For each named context, the context is applied and the tests are run. It
+ # allows to have multiple shared contexts and only one example group,
+ # instead of having shared examples and multiple contexts including the
+ # shared examples. It generally reads better.
+ #
+ # @example
+ #
+ # RSpec.describe "something" do
+ # shared_context "early in the morning" do
+ # let(:time) { "06:30" }
+ # end
+ #
+ # shared_context "late in the evening" do
+ # let(:time) { "23:00" }
+ # end
+ #
+ # for_each_context "early in the morning",
+ # "late in the evening" do
+ # it "has energy" do
+ # expect(body.energy_level).to eq(100)
+ # end
+ # end
+ # end
+ def for_each_context(*context_names, &blk)
+ context_names.each do |context_name|
+ context context_name do
+ include_context context_name
+
+ instance_exec(&blk)
+ end
+ end
+ end
+ end
+end
+
+RSpec.configure do |config|
+ config.extend RSpecOpExt::ForEachContext
+end
diff --git a/spec/support/table_helpers.rb b/spec/support/table_helpers.rb
index e4597d06e140..7819e5c8fa06 100644
--- a/spec/support/table_helpers.rb
+++ b/spec/support/table_helpers.rb
@@ -36,6 +36,7 @@
match do |actual_work_packages|
expected_data = TableHelpers::TableData.for(expected)
actual_data = TableHelpers::TableData.from_work_packages(actual_work_packages, expected_data.columns)
+ actual_data.order_like!(expected_data)
representer = TableHelpers::TableRepresenter.new(tables_data: [expected_data, actual_data],
columns: expected_data.columns)
diff --git a/spec/support/table_helpers/example_methods.rb b/spec/support/table_helpers/example_methods.rb
index 5843b2744ac8..f7ea096f8eb5 100644
--- a/spec/support/table_helpers/example_methods.rb
+++ b/spec/support/table_helpers/example_methods.rb
@@ -51,7 +51,8 @@ def create_table(table_representation)
# Expect the given work packages to match a visual table representation.
#
- # It uses +match_table+ internally.
+ # It uses +match_table+ internally and reloads the work packages from
+ # database before comparing.
#
# For instance:
#
@@ -66,6 +67,7 @@ def create_table(table_representation)
# is equivalent to:
#
# it 'is scheduled' do
+ # work_packages.each(&:reload)
# expect(work_packages).to match_table(<<~TABLE)
# subject | work | derived work |
# parent | 1h | 3h |
@@ -73,6 +75,7 @@ def create_table(table_representation)
# TABLE
# end
def expect_work_packages(work_packages, table_representation)
+ work_packages.each(&:reload)
expect(work_packages).to match_table(table_representation)
end
end
diff --git a/spec/support/table_helpers/let_work_packages.rb b/spec/support/table_helpers/let_work_packages.rb
index c7982c267a7e..bc62f2cf3da0 100644
--- a/spec/support/table_helpers/let_work_packages.rb
+++ b/spec/support/table_helpers/let_work_packages.rb
@@ -49,7 +49,7 @@ module LetWorkPackages
# let!(:_table) do
# create_table(table_representation)
# end
- # let!(:table_work_packages) do
+ # let(:table_work_packages) do
# _table.work_packages
# end
# let(:parent) do
@@ -70,5 +70,48 @@ def let_work_packages(table_representation)
let(identifier) { _table.work_package(identifier) }
end
end
+
+ # Declare work packages and relations from a visual chart representation.
+ #
+ # It uses +create_table+ internally and is useful to have direct access
+ # to the created work packages.
+ #
+ # To see supported columns, see +TableHelpers::Column+.
+ #
+ # For instance:
+ #
+ # shared_let_work_packages(<<~TABLE)
+ # hierarchy | work |
+ # parent | 1h |
+ # child | 2.5h |
+ # another one | |
+ # TABLE
+ #
+ # is equivalent to:
+ #
+ # shared_let(:_table) do
+ # create_table(table_representation)
+ # end
+ # shared_let(:table_work_packages) do
+ # _table.work_packages
+ # end
+ # shared_let(:parent) do
+ # _table.work_package(:parent)
+ # end
+ # shared_let(:child) do
+ # _table.work_package(:child)
+ # end
+ # shared_let(:another_one) do
+ # _table.work_package(:another_one)
+ # end
+ def shared_let_work_packages(table_representation)
+ shared_let(:_table) { create_table(table_representation) }
+
+ table_data = TableData.for(table_representation)
+ shared_let(:table_work_packages) { _table.work_packages }
+ table_data.work_package_identifiers.each do |identifier|
+ shared_let(identifier) { _table.work_package(identifier) }
+ end
+ end
end
end
diff --git a/spec/support/table_helpers/table_data.rb b/spec/support/table_helpers/table_data.rb
index 0659f89280f3..59186d3463aa 100644
--- a/spec/support/table_helpers/table_data.rb
+++ b/spec/support/table_helpers/table_data.rb
@@ -83,6 +83,15 @@ def create_work_packages
Table.new(work_packages_by_identifier)
end
+ def order_like!(other_table)
+ ordered_identifiers = other_table.work_package_identifiers
+ extra_identifiers = work_package_identifiers - ordered_identifiers
+ @work_packages_data = work_packages_data
+ .index_by { _1[:identifier] }
+ .values_at(*(ordered_identifiers + extra_identifiers))
+ .compact
+ end
+
class Factory
attr_reader :table_data, :work_packages_by_identifier
diff --git a/spec/support/table_helpers/table_parser.rb b/spec/support/table_helpers/table_parser.rb
index 80466f3e45d3..c3faa62614be 100644
--- a/spec/support/table_helpers/table_parser.rb
+++ b/spec/support/table_helpers/table_parser.rb
@@ -31,14 +31,16 @@
module TableHelpers
class TableParser
def parse(representation)
- headers, *rows = representation.split("\n")
- headers = split(headers)
- rows = rows.filter_map { |row| parse_row(row, headers) }
- work_packages_data = rows.map.with_index do |row, index|
+ headers, *rows = representation.split("\n").filter_map { |line| split_line_into_cells(line) }
+ work_packages_data = rows.map.with_index do |cells, index|
+ if cells.size > headers.size
+ raise ArgumentError, "Too many cells in row #{index + 1}, have you forgotten some headers?"
+ end
+
{
attributes: {},
index:,
- row:
+ row: headers.zip(cells).to_h
}
end
headers.each do |header|
@@ -50,13 +52,12 @@ def parse(representation)
private
- def parse_row(row, headers)
- case row
+ def split_line_into_cells(line)
+ case line
when "", /^\s*#/
# noop
else
- values = split(row)
- headers.zip(values).to_h
+ split(line)
end
end
diff --git a/spec/support_spec/table_helpers/table_data_spec.rb b/spec/support_spec/table_helpers/table_data_spec.rb
index 0fbecea1677c..f6ffe8581941 100644
--- a/spec/support_spec/table_helpers/table_data_spec.rb
+++ b/spec/support_spec/table_helpers/table_data_spec.rb
@@ -145,5 +145,69 @@ module TableHelpers
.not_to raise_error
end
end
+
+ describe "#order_like" do
+ it "orders the table data like the given table" do
+ table_representation = <<~TABLE
+ | subject | remaining work |
+ | work package | 3h |
+ | another one | |
+ TABLE
+ table_data = described_class.for(table_representation)
+
+ other_table_representation = <<~TABLE
+ | subject | remaining work |
+ | another one | |
+ | work package | 3h |
+ TABLE
+ other_table_data = described_class.for(other_table_representation)
+ expect(table_data.work_package_identifiers).to eq(%i[work_package another_one])
+
+ table_data.order_like!(other_table_data)
+ expect(table_data.work_package_identifiers).to eq(%i[another_one work_package])
+ end
+
+ it "ignores unknown rows from the given table" do
+ table_representation = <<~TABLE
+ | subject | remaining work |
+ | work package | 3h |
+ | another one | |
+ TABLE
+ table_data = described_class.for(table_representation)
+
+ other_table_representation = <<~TABLE
+ | subject | remaining work |
+ | another one | |
+ | work package | 3h |
+ | unknown one | |
+ TABLE
+ other_table_data = described_class.for(other_table_representation)
+ expect(table_data.work_package_identifiers).to eq(%i[work_package another_one])
+
+ table_data.order_like!(other_table_data)
+ expect(table_data.work_package_identifiers).to eq(%i[another_one work_package])
+ end
+
+ it "appends to the bottom the rows missing in the given table" do
+ table_representation = <<~TABLE
+ | subject | remaining work |
+ | work package | 3h |
+ | extra one | |
+ | another one | |
+ TABLE
+ table_data = described_class.for(table_representation)
+
+ other_table_representation = <<~TABLE
+ | subject | remaining work |
+ | another one | |
+ | work package | 3h |
+ TABLE
+ other_table_data = described_class.for(other_table_representation)
+ expect(table_data.work_package_identifiers).to eq(%i[work_package extra_one another_one])
+
+ table_data.order_like!(other_table_data)
+ expect(table_data.work_package_identifiers).to eq(%i[another_one work_package extra_one])
+ end
+ end
end
end
diff --git a/spec/support_spec/table_helpers/table_parser_spec.rb b/spec/support_spec/table_helpers/table_parser_spec.rb
index 12d0b34e2f16..2e5358ec5748 100644
--- a/spec/support_spec/table_helpers/table_parser_spec.rb
+++ b/spec/support_spec/table_helpers/table_parser_spec.rb
@@ -53,6 +53,7 @@
it "ignores comments and empty lines" do
table = <<~TABLE
+ # this comment is ignored
| subject |
# this comment and the following empty line are ignored
@@ -72,6 +73,25 @@
.to raise_error(ArgumentError, 'Please use "remaining work" instead of "remaining hours"')
end
+ it "raises an error if there are more cells than headers in a row" do
+ table = <<~TABLE
+ subject | work
+ wp | 4h | 6h
+ TABLE
+ expect { described_class.new.parse(table) }
+ .to raise_error(ArgumentError, "Too many cells in row 1, have you forgotten some headers?")
+ end
+
+ it "is ok to have more headers than cells (value of missing cells will be nil)" do
+ table = <<~TABLE
+ subject | work | remaining work
+ wp | 4h
+ TABLE
+ parsed_data = described_class.new.parse(table)
+ expect(parsed_data.dig(0, :attributes, :estimated_hours)).to eq(4.0)
+ expect(parsed_data.dig(0, :attributes, :remaining_hours)).to be_nil
+ end
+
describe "subject column" do
let(:table) do
<<~TABLE
diff --git a/spec/workers/work_packages/progress/apply_statuses_p_complete_job_spec.rb b/spec/workers/work_packages/progress/apply_statuses_change_job_spec.rb
similarity index 56%
rename from spec/workers/work_packages/progress/apply_statuses_p_complete_job_spec.rb
rename to spec/workers/work_packages/progress/apply_statuses_change_job_spec.rb
index 185fead8735d..97ad3d2cc0d2 100644
--- a/spec/workers/work_packages/progress/apply_statuses_p_complete_job_spec.rb
+++ b/spec/workers/work_packages/progress/apply_statuses_change_job_spec.rb
@@ -28,11 +28,23 @@
require "rails_helper"
-RSpec.describe WorkPackages::Progress::ApplyStatusesPCompleteJob do
+RSpec.describe WorkPackages::Progress::ApplyStatusesChangeJob do
shared_let(:author) { create(:user) }
shared_let(:priority) { create(:priority, name: "Normal") }
shared_let(:project) { create(:project, name: "Main project") }
+
+ # statuses for work-based mode
shared_let(:status_new) { create(:status, name: "New") }
+ shared_let(:status_wip) { create(:status, name: "In progress") }
+ shared_let(:status_closed) { create(:status, name: "Closed") }
+
+ # statuses for status-based mode
+ shared_let(:status_0p_todo) { create(:status, name: "To do (0%)", default_done_ratio: 0) }
+ shared_let(:status_40p_doing) { create(:status, name: "Doing (40%)", default_done_ratio: 40) }
+ shared_let(:status_100p_done) { create(:status, name: "Done (100%)", default_done_ratio: 100) }
+
+ # statuses for both work-based and status-based modes
+ shared_let(:status_excluded) { create(:status, :excluded_from_totals, name: "Excluded") }
before_all do
set_factory_default(:user, author)
@@ -42,20 +54,16 @@
set_factory_default(:status, status_new)
end
- shared_let(:status_0p_todo) { create(:status, name: "To do (0%)", default_done_ratio: 0) }
- shared_let(:status_40p_doing) { create(:status, name: "Doing (40%)", default_done_ratio: 40) }
- shared_let(:status_100p_done) { create(:status, name: "Done (100%)", default_done_ratio: 100) }
-
subject(:job) { described_class }
def expect_performing_job_changes(from:, to:,
- cause_type: "status_p_complete_changed",
- status_name: "New",
+ cause_type: "status_changed",
+ status_name: "Some status name",
status_id: 99,
- change: [33, 66])
+ changes: { "default_done_ratio" => [33, 66] })
table = create_table(from)
- job.perform_now(cause_type:, status_name:, status_id:, change:)
+ job.perform_now(cause_type:, status_name:, status_id:, changes:)
table.work_packages.map(&:reload)
expect_work_packages(table.work_packages, to)
@@ -85,6 +93,89 @@ def expect_performing_job_changes(from:, to:,
)
end
end
+
+ context "when a status is being excluded from progress calculation" do
+ it "computes totals of the parent having work when all children are excluded" do
+ expect_performing_job_changes(
+ from: <<~TABLE,
+ hierarchy | status | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete
+ parent | In progress | 10h | 3h | 70% | 20h | 5h | 75%
+ child | Excluded | 10h | 2h | 50% | | |
+ TABLE
+ to: <<~TABLE
+ subject | status | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete
+ parent | In progress | 10h | 3h | 70% | 10h | 3h | 70%
+ child | Excluded | 10h | 2h | 50% | | |
+ TABLE
+ )
+ end
+
+ it "keeps the totals unset if work, remaining work, and % complete are all nil" do
+ expect_performing_job_changes(
+ from: <<~TABLE,
+ hierarchy | status | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete
+ parent | In progress | | | | | |
+ child | Excluded | | | | | |
+ TABLE
+ to: <<~TABLE
+ subject | status | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete
+ parent | In progress | | | | | |
+ child | Excluded | | | | | |
+ TABLE
+ )
+ end
+
+ describe "general case" do
+ # The work packages are created like if the status is not excluded yet
+ shared_let_work_packages(<<~TABLE)
+ hierarchy | status | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete
+ grandparent | New | 1h | 0.6h | 40% | 24h | 11.3h | 53%
+ parent | Excluded | 4h | 1h | 75% | 23h | 10.7h | 53%
+ child 1 | Excluded | 9h | 7.2h | 20% | | |
+ child 2 | In progress | 5h | 2.5h | 50% | | |
+ child 3 | Closed | 5h | 0h | 100% | | |
+ TABLE
+
+ before do
+ job.perform_now(
+ cause_type: "status_changed",
+ status_name: status_excluded.name,
+ status_id: status_excluded.id,
+ changes: { "excluded_from_totals" => [false, true] }
+ )
+ table_work_packages.map(&:reload)
+ end
+
+ it "recomputes totals without the values from work packages having the excluded status" do
+ expect_work_packages(table_work_packages, <<~TABLE)
+ subject | status | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete
+ grandparent | New | 1h | 0.6h | 40% | 11h | 3.1h | 72%
+ parent | Excluded | 4h | 1h | 75% | 10H | 2.5h | 75%
+ child 1 | Excluded | 9h | 7.2h | 20% | | |
+ child 2 | In progress | 5h | 2.5h | 50% | | |
+ child 3 | Closed | 5h | 0h | 100% | | |
+ TABLE
+ end
+
+ it "adds a relevant journal entry for the parent with recomputed total" do
+ changed_worked_packages = [grandparent, parent]
+ changed_worked_packages.each do |work_package|
+ expect(work_package.journals.count).to eq(2), "expected #{work_package} to have a new journal"
+ last_journal = work_package.last_journal
+ expect(last_journal.user).to eq(User.system)
+ expect(last_journal.cause_type).to eq("status_changed")
+ expect(last_journal.cause_status_name).to eq("Excluded")
+ expect(last_journal.cause_status_id).to eq(status_excluded.id)
+ expect(last_journal.cause_status_changes).to eq({ "excluded_from_totals" => [false, true] })
+ end
+
+ unchanged_work_packages = table_work_packages - changed_worked_packages
+ unchanged_work_packages.each do |work_package|
+ expect(work_package.journals.count).to eq(1), "expected #{work_package} not to have new journals"
+ end
+ end
+ end
+ end
end
context "when in status-based mode",
@@ -155,6 +246,57 @@ def expect_performing_job_changes(from:, to:,
end
end
+ context "when a status is being excluded from progress calculation" do
+ # The work packages are created like if the status is not excluded yet
+ shared_let_work_packages(<<~TABLE)
+ hierarchy | status | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete
+ grandparent | Doing (40%) | 1h | 0.6h | 40% | 24h | 16.6h | 31%
+ parent | Excluded | 4h | 4h | 0% | 23h | 16h | 30%
+ child 1 | Excluded | 9h | 9h | 0% | | |
+ child 2 | Doing (40%) | 5h | 3h | 40% | | |
+ child 3 | Done (100%) | 5h | 0h | 100% | | |
+ TABLE
+
+ before do
+ job.perform_now(
+ cause_type: "status_changed",
+ status_name: status_excluded.name,
+ status_id: status_excluded.id,
+ changes: { "excluded_from_totals" => [false, true] }
+ )
+ table_work_packages.map(&:reload)
+ end
+
+ it "recomputes totals without the values from work packages having the excluded status" do
+ expect_work_packages(table_work_packages, <<~TABLE)
+ subject | status | work | remaining work | % complete | ∑ work | ∑ remaining work | ∑ % complete
+ grandparent | Doing (40%) | 1h | 0.6h | 40% | 11h | 3.6h | 67%
+ parent | Excluded | 4h | 4h | 0% | 10h | 3h | 70%
+ child 1 | Excluded | 9h | 9h | 0% | | |
+ child 2 | Doing (40%) | 5h | 3h | 40% | | |
+ child 3 | Done (100%) | 5h | 0h | 100% | | |
+ TABLE
+ end
+
+ it "adds a relevant journal entry for the parent with recomputed total" do
+ changed_worked_packages = [grandparent, parent]
+ changed_worked_packages.each do |work_package|
+ expect(work_package.journals.count).to eq(2), "expected #{work_package} to have a new journal"
+ last_journal = work_package.last_journal
+ expect(last_journal.user).to eq(User.system)
+ expect(last_journal.cause_type).to eq("status_changed")
+ expect(last_journal.cause_status_name).to eq("Excluded")
+ expect(last_journal.cause_status_id).to eq(status_excluded.id)
+ expect(last_journal.cause_status_changes).to eq({ "excluded_from_totals" => [false, true] })
+ end
+
+ unchanged_work_packages = table_work_packages - changed_worked_packages
+ unchanged_work_packages.each do |work_package|
+ expect(work_package.journals.count).to eq(1), "expected #{work_package} not to have new journals"
+ end
+ end
+ end
+
describe "journals" do
# rubocop:disable RSpec/ExampleLength
it "creates journal entries for modified work packages on status % complete change" do
@@ -171,19 +313,19 @@ def expect_performing_job_changes(from:, to:,
child 1 | Doing (40%) | 10h | 6h | 40% | | |
child 2 | Done (100%) | 10h | 0h | 100% | | |
TABLE
- cause_type: "status_p_complete_changed",
+ cause_type: "status_changed",
status_name: status_40p_doing.name,
status_id: status_40p_doing.id,
- change: [20, 40]
+ changes: { "default_done_ratio" => [20, 40] }
)
[parent, child1].each do |work_package|
expect(work_package.journals.count).to eq 2
last_journal = work_package.last_journal
expect(last_journal.user).to eq(User.system)
- expect(last_journal.cause_type).to eq("status_p_complete_changed")
+ expect(last_journal.cause_type).to eq("status_changed")
expect(last_journal.cause_status_name).to eq("Doing (40%)")
expect(last_journal.cause_status_id).to eq(status_40p_doing.id)
- expect(last_journal.cause_status_p_complete_change).to eq([20, 40])
+ expect(last_journal.cause_status_changes).to eq({ "default_done_ratio" => [20, 40] })
end
# unchanged => no new journals
@@ -241,10 +383,10 @@ def expect_performing_job_changes(from:, to:,
.and_return(nil)
begin
- job.perform_now(cause_type: "status_p_complete_changed",
+ job.perform_now(cause_type: "status_changed",
status_name: "New",
status_id: 99,
- change: [33, 66])
+ changes: { "default_done_ratio" => [33, 66] })
rescue StandardError
end
end